You are here:   Blog
Register   |  Login

 

May 4

Written by: Michael Washington
5/4/2013 10:29 AM  RssIcon

image

The primary reason you may want to use WCF RIA Services with Visual Studio LightSwitch is to:

  • Combine more than one entity into a single entity.
  • Eliminate unneeded columns in an entity to improve performance (otherwise large amounts of data, for example pictures, will be transmitted even when they are not shown).
  • Implement calculated fields that allow the resulting values to be searchable and sortable.

Also, the LightSwitch OData services return one Entity collection at a time. This makes grouping and totaling across Entity collections difficult. Using WCF RIA Services provides a clean elegant solution.

The official documentation from Microsoft on creating WCF RIA Services is available at this link.

WCF RIA Services have been covered previously on this site. This article reflects the latest changes in Visual Studio 2012 update 2.

The Sample Application

image

In the Flower Shop application used in the tutorial: Calling LightSwitch 2011 OData Using Server Side Code we have computed fields in the FlowerShopOrder Entity.

This allows us to easily display the Order Total.

image

However, if we connect to the OData service for that Entity, we see it does not contain the Order Total.

To get this data, it requires additional queries of the Product Entity to get the Product price, and all the related Order Detail Entities to calculate the Order Total.

This is a problem because not only does it require additional database queries, it requires the client consuming the OData feed to now be responsible for complex business logic.

We can create an OData service with these computed fields using a WCF RIA Service.

Create A WCF RIA Service

image

First, Add a New Project to the existing LightSwitch project.

image

Create a .NET Framework 4 Class Library called WCF_RIA_Project.

image

Delete the Class1.cs file that is automatically created.

image

Add a New Item to WCF_RIA_Project.

image

Add a Domain Service Class called WCF_RIA_Service.cs.

image

When the Add New Domain Service Class box comes up, uncheck Enable client access. Click OK.

This domain class will be exposed by LightSwitch and will pass through its security and business rules.

image

We need additional references, add the following references to the WCF_RIA_Project

image

  • System.ComponentModel.DataAnnotations
  • System.Configuration
  • System.Data.Entity
  • System.Runtime.Serialization
  • System.ServiceModel.DomainServices.Server (Look in %ProgramFiles%\Microsoft SDKs\RIA Services\v1.0\Libraries\Server)
  • System.Web

Add the following Using Statements to the class:

image

using System.Data.EntityClient;
using System.Web.Configuration;
using LightSwitchApplication.Implementation;

(LightSwitchApplication will display with a squiggly red line because the class is missing, but it will be added in the next step)

Reference The LightSwitch Object Context

Now, we will add code from the LightSwitch project to our WCF RIA Service project. We will add a class that LightSwitch automatically creates, that connects to the database that LightSwitch uses.

We will use this class in our WCF RIA Service to communicate with the LightSwitch database.

image

Right-click on the WCF_RIA_Project and select Add then Existing Item.

image

Navigate to ..Server\GeneratedArtifacts (in the LightSwitch project)and click on ApplicationDataObjectContext.cs and Add As Link.

We used “add As Link” so that whenever LightSwitch updates this class, our WCF RIA Service is also updated. This is how our WCF RIA Service would be able to see any new Entities (tables) that were added, deleted, or changed.

image

The file will show in the project.

 

Create the Domain Service

Replace the entire code for the WCF_RIA_Service.cs file with the following:

namespace WCF_RIA_Project
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.ComponentModel.DataAnnotations;
    using System.Linq;
    using System.ServiceModel.DomainServices.Hosting;
    using System.ServiceModel.DomainServices.Server;
    using System.Data.EntityClient;
    using System.Web.Configuration;
    using LightSwitchApplication.Implementation;
    // This class is used as the class that is returned
    // This can have any 'shape' you desire
    // Make sure this is outside of the WCF_RIA_Service class
    // but inside the WCF_RIA_Project namespace
    public class EnhancedFlowerShopOrder
    {
        [Key]
        public int ID { get; set; }
        public DateTime OrderDate { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public decimal OrderTotal { get; set; }
    }
    public class WCF_RIA_Service : DomainService
    {
        // This Context property is code that connects to the LightSwitch database
        // The code in the Database connection region can be reused as it is 
        #region Database connection
        private ApplicationData m_context;
        public ApplicationData Context
        {
            get
            {
                if (this.m_context == null)
                {
                    string connString =
                        System.Web.Configuration.WebConfigurationManager
                        .ConnectionStrings["_IntrinsicData"].ConnectionString;
                    EntityConnectionStringBuilder builder = new EntityConnectionStringBuilder();
                    builder.Metadata =
                        "res://*/ApplicationData.csdl|res://*/ApplicationData.ssdl|res://*/ApplicationData.msl";
                    builder.Provider =
                        "System.Data.SqlClient";
                    builder.ProviderConnectionString = connString;
                    this.m_context = new ApplicationData(builder.ConnectionString);
                }
                return this.m_context;
            }
        }
        #endregion
        [Query(IsDefault = true)]
        public IQueryable<EnhancedFlowerShopOrder> GetAllOrders()
        {
            // Get all the Orders
            var colFlowerShopOrders = from Order in this.Context.FlowerShopOrders
                                      // Shape the results into the 
                                      // EnhancedFlowerShopOrder class
                                      select new EnhancedFlowerShopOrder
                                      {
                                          // The Order ID
                                          ID = Order.Id,
                                          // The Order Date
                                          OrderDate = Order.OrderDate,
                                          // The first name of the Customer
                                          FirstName = Order.FlowerShopCustomer.FirstName,
                                          // The last name of the Customer
                                          LastName = Order.FlowerShopCustomer.LastName,
                                          // The order Total
                                          OrderTotal =
                                          // Get all order details lines of the Order
                                          (from FlowerShopOrderDetail in Order.FlowerShopOrderDetail
                                           // Group the products in the Order Details
                                           group FlowerShopOrderDetail 
                                           by FlowerShopOrderDetail.Id into g
                                           // Shape a new entity
                                           select new
                                           {
                                               // Create a total property that is the Quantity times the
                                               // Product price
                                               TotalOrder = g.Sum(x => x.Quantity) 
                                               * g.Sum(x => x.FlowerShopProduct.Price),
                                           }).Sum(x => x.TotalOrder) // Add the sum of all the TotalOrders
                                      };
            return colFlowerShopOrders;
        }
        // Override the Count method in order for paging to work correctly
        protected override int Count<T>(IQueryable<T> query)
        {
            return query.Count();
        }
    }
}

Consume The WCF RIA Service

image

Build the solution.

(You will get a ton or warnings in the immediate window, you can ignore them)

image

In the Solution Explorer (of the LightSwitch project), right-click on the Data Sources folder and select Add Data Source.

image

Select WCF RIA Service and click Next.

image

Click Add Reference.

image

Select Solution, then Projects, then check the box next to the WCF_RIA_Project.

Click OK.

image

Wait for the service to show up in the selection box, select it and click Next.

image

Check the box next to the Entities, and click Finish.

image

The Entity will display.

image

We can now add the collection to a screen as we would any other collection.

image

All the values are searchable and sortable.

 

WCF RIA Services Can Read, Update, Insert, and Delete

See the article: WCF RIA Service: Combining Two Tables for an example.

 

Download Code

The LightSwitch project is available at http://lightswitchhelpwebsite.com/Downloads.aspx

(you must have Visual Studio 2012 Update 2 installed to run the code)

22 comment(s) so far...


Gravatar

Re: Creating a WCF RIA Service for Visual Studio 2012 (Update 2 and higher)

Thanks again for a great sample Michael. I have been searching for a way to call a Stored Procedure (to get records, not do an update) for a complex set of data in Lightswitch and your article is a more detailed step by step of some others I had been trying to follow without success.

I have gotten through most of your sample, and applied it to my project, but I am stuck at the line below:
public IQueryable GetAllOrders()
I have a default query that returns all records called GetOpenOrders() and my line reads:
public IQueryable GetAllOrders()
and I am getting build errors about TrackingStatusOrders not being found in my project. My understanding (guess really) is that TrackingStatusOrders is an IQueryable class that is created for GetOpenOrders() to be loaded into by the code that follows that creates the collection of orders and assigns it to the class. Am I missing something? Do you have a class called EnhancedFlowerShopOrder that I do not see, or is it in the data sources? When searching for info on IQueryable, I am just flooded with results, and I am hoping you can clear that up, since I do not see reference to EnhancedFlowerShopOrder in the project before this line.
Thanks again for the wonderful work you are doing with Beth and the MS team.

By Dan Gleason on   5/6/2013 1:47 PM
Gravatar

Re: Creating a WCF RIA Service for Visual Studio 2012 (Update 2 and higher)

@Dan Gleason - I do have a class called "EnhancedFlowerShopOrder" (it is there in my code) and you need to create a class like it as the class that is returned by your IQueryable.

By Michael Washington on   5/6/2013 1:49 PM
Gravatar

Re: Creating a WCF RIA Service for Visual Studio 2012 (Update 2 and higher)

Howdy! Thanks for the article! I was wondering if it's possible to access Lightswitch's membership from this. I'd like to create an interface for managing users since each user A) has custom data associated with them in a custom table and B) has relationships to other data in lightswitch.

By Richard Simpson on   5/9/2013 9:07 PM
Gravatar

Re: Creating a WCF RIA Service for Visual Studio 2012 (Update 2 and higher)

@Richard Simpson - It should be possible but I have no code examples.

By Michael Washington on   5/9/2013 9:07 PM
Gravatar

Re: Creating a WCF RIA Service for Visual Studio 2012 (Update 2 and higher)

Thanks! Just one question. Why you're using a "Class Library" project instead of using directly a "WCF Ria Service Library" ?

By Pablo on   5/10/2013 10:37 AM
Gravatar

Re: Creating a WCF RIA Service for Visual Studio 2012 (Update 2 and higher)

@Pablo - When I tried that in the past it did not work for me.

By Michael Washington on   5/10/2013 10:37 AM
Gravatar

Re: Creating a WCF RIA Service for Visual Studio 2012 (Update 2 and higher)

Michael - thanks for all the great posts over the past couple years. I've used them extensively in my exploration of Lightswitch.

Stupid question: why can't I create a domain service class inside the Lightswitch server project? I'm sure there's a good reason for it, but it seems like it would make everything much easier.

Thanks
Jay

By Jay Turpin on   5/29/2013 10:37 AM
Gravatar

Re: Creating a WCF RIA Service for Visual Studio 2012 (Update 2 and higher)

@Jay Turpin - In the past LightSwitch would not see it there. However, I have not tried that in years.

By Michael Washington on   5/29/2013 10:37 AM
Gravatar

Re: Creating a WCF RIA Service for Visual Studio 2012 (Update 2 and higher)

@JohnMarsing - Please download the code and compare it to your own.

By Michael Washington on   5/30/2013 8:31 PM
Gravatar

Re: Creating a WCF RIA Service for Visual Studio 2012 (Update 2 and higher)

I see what the problem is, my LS app was not an HTML client project.

I also see how I can do this with the article you mentioned above "WCF RIA Service: Combining Two Tables" where you need to use the ApplicationData.cs file.

By JohnMarsing on   5/31/2013 2:03 PM
Gravatar

Re: Creating a WCF RIA Service for Visual Studio 2012 (Update 2 and higher)

@JohnMarsing - Thank you for following up.

By Michael Washington on   5/31/2013 2:15 PM
Gravatar

Re: Creating a WCF RIA Service for Visual Studio 2012 (Update 2 and higher)

Michael,

Nice article. Question about using RIA to expose a database updatable view...in order to have searchable\sortable 'computed properties'

If the database did the aggregations\calculations in the view T-SQL rather than in the RIA code, would that mean that lightswitch would not recalculate on screens automatically? In other words, after updating quantity or price, in order to display calculations on browse screen, extra code would be required to update the collection and refresh the screen. Is that correct?

By joshBooker on   6/4/2013 10:21 AM
Gravatar

Re: Creating a WCF RIA Service for Visual Studio 2012 (Update 2 and higher)

@joshBooker - When you refresh the collection you would get the updated calculations just as you would any other field. The key is that you would have to have code to do the refresh.

By Michael Washington on   6/4/2013 10:23 AM
Gravatar

Re: Creating a WCF RIA Service for Visual Studio 2012 (Update 2 and higher)

Thanks Michael...just to be clear...the extra refresh code is not required when calculations are done in RIA code as in your example since lightswitch 'understands' the linq query on the client-side, correct? As a db guy, I'm more comfortable with t-sql. Since RIA is necessary to easily join tables and make computations sort/seachable, I'm trying to understand the pros and cons of putting aggregates in db vs. RIA. Thanks again.

By joshBooker on   6/4/2013 12:41 PM
Gravatar

Re: Creating a WCF RIA Service for Visual Studio 2012 (Update 2 and higher)

@joshBooker - It's not really a calculation, it is just another field in the Entity that happens to represent the result of a calculation. A "real calculated field" would update the calculation without requiring you to save the Entity first. With all that said, it is the same if you use a T-SQL View or a WCF RIA Service.

By Michael Washington on   6/4/2013 12:44 PM
Gravatar

Re: Creating a WCF RIA Service for Visual Studio 2012 (Update 2 and higher)

Hi, Michael.
I'm in the middle of creating a WCF RIA Services based lightswitch project. I've created the domain service class. The input datas come from a WCF service (don't ask...). The WCF RIA Service is working just fine, I could make the datasource, and a screen as well. When I want to start the application, during the loading i get this error: "The maximum message size quota for incoming messages (65536) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element." I figured out that the amount of my input data is hight, but where could I set the maximum message size quota? I tried in the lightswitch client side ServiceReferences.Client.Config file, or the web.config file with no luck...
Thanks

By AdM on   7/10/2013 4:19 AM
Gravatar

Re: Creating a WCF RIA Service for Visual Studio 2012 (Update 2 and higher)

@Adm - I don't know. I have never had that error before. Make a post in the LightSwitch forums: http://social.msdn.microsoft.com/Forums/vstudio/en-US/home?forum=lightswitch

By Michael Washington on   7/10/2013 4:20 AM
Gravatar

Re: Creating a WCF RIA Service for Visual Studio 2012 (Update 2 and higher)

I followed your instructions, however when I went to consume the WCF RIA service, it did not display the classes that I built. I investigated some more and realized that the RIA service needs to point to the .NET 4.0, mine was set to 4.5. You can change the framework in the properties of the RIA class.

Thanks for your help in this. This will really help with my efforts to integrate more/better data in to HTML screens, eliminate code and table space, and make reporting easier as I integrate with Office.

Thanks!

By Louis Garcia on   7/11/2013 4:29 AM
Gravatar

Re: Creating a WCF RIA Service for Visual Studio 2012 (Update 2 and higher)

Hi Michael.
Congratulations for the great work you're doing in supporting LightSwitch community.
When I debug my application, my screen with the RIA data shows nothing, only a cross red square, and says as a description, that it can not read any data and that I must verify my network connection.
Can you help me with this

By Joao Silva on   7/20/2013 7:00 AM
Gravatar

Re: Creating a WCF RIA Service for Visual Studio 2012 (Update 2 and higher)

@Joao Silva- I can't tell what the problem is. If my sample works for you, compare the code in the WCF RIA Service to your own. Also ensure you are using asp.net 4.0 not asp.net 4.5. If it still doesn't work post the contents of your WCF RIA Service to the official LightSwitch forums at: http://social.msdn.microsoft.com/Forums/vstudio/en-US/home?forum=lightswitch

By Michael Washington on   7/20/2013 9:00 AM
Gravatar

Re: Creating a WCF RIA Service for Visual Studio 2012 (Update 2 and higher)

@Joao Silva- I must insist that you follow my wishes and post to the official LightSwitch forums at: http://social.msdn.microsoft.com/Forums/vstudio/en-US/home?forum=lightswitch

By Michael Washington on   7/22/2013 8:25 AM
Gravatar

Re: Creating a WCF RIA Service for Visual Studio 2012 (Update 2 and higher)

Thank you this was Exactly what i Searched for...

By Lenine prasad on   1/3/2014 4:45 AM

Your name:
Gravatar Preview
Your email:
(Optional) Email used only to show Gravatar.
Your website:
Title:
Comment:
Security Code
CAPTCHA image
Enter the code shown above in the box below
Add Comment   Cancel 
Microsoft Visual Studio is a registered trademark of Microsoft Corporation / LightSwitch is a registered trademark of Microsoft Corporation