(X) Hide this
    • Login
    • Join
      • Generate New Image
        By clicking 'Register' you accept the terms of use .

Building N-Tier business applications with .NET RIA Services – Part I

(13 votes)
Zoltan Arvai
>
Zoltan Arvai
Joined Jul 20, 2009
Articles:   7
Comments:   5
More Articles
17 comments   /   posted on Nov 05, 2009
Categories:   Data Access , Line-of-Business

This article is compatible with the latest version of Silverlight.

Introduction

In this series of articles we will talk about building N-Tier Silverlight business application, why we want to use multiple tiers, what problems we have to face and how .NET RIA Services can help us solve our issues.

Going N-Tier

If you develop complex business applications with a large codebase that can easily adapt to changing environments you introduce multiple tiers or layers. For example, you create a Data Access Layer that communicates with your data source whatever that is and passes the requested data to the layer above in object oriented form. The layers above don’t know and don’t want to know anything about how persistence actually happens. All that they want to do is: GetProducts, SaveChanges or PersistChanges. You can have many different layers like Business Logic Layer, Service Layer or Presentation Layer to ensure your code is flexible, well-structured and strictly separated.

So you decided going n-tier which is not a really big surprise since you don’t have a choice. If you work with Silverlight you have at least 3 layers. You don’t have ADO.NET libraries in Silverlight so you can’t interact with a database directly (and you shouldn’t do that anyway). So here is what you should have (at least):

  1. Your Silverlight Application - Presentation layer
  2. A WCF Service – Service Layer
  3. Your Database / additional ADO.NET logic to interact with your database – Persistence Layer

Issues with N-Tier development

You have a nice architecture now but it introduces new problems. Now let’s think about how you want to code against these layers. In your Presentation Layer you would like to call a GetProducts method and retrieve your Product list from your Service Layer. You do whatever you want with this list. You modify Product instances in it, add new ones or delete old ones. After you’re done all you want to do is “SaveChanges” back to the database. But you can’t. This would mean that you have client-side change tracking and identity management. Even if you had this on the server side you had lost it as soon as your data has left the server. Solving this problem by yourself would mean a lot of code.

Building a Service Layer Manually for CRUD Support

If you have several entities mapped to tables on the server side you probably want to enable CRUD operations on them. In this case you’d have to write all these operations by yourself. For example, CRUD operations for the Product entity would look something like this:

  • GetProducts
  • InsertProduct(Product p)
  • DeleteProduct(Product p)
  • UpdateProduct(Product p)

Validation issues

Now, if you want to save changes created by user input back to the database you need validation. When you use technologies like Entity Framework or LinqToSql you may notice that the entities setters contain a call to a partial method where you can handle validation. And we know that Silverlight validation mechanism is based on throwing exceptions in property setters. So this is pretty much the place where you should write this logic. Validation needs to happen on both client and server side. Server-side validation ensures that invalid data sent by hacked clients won’t cause any problems. Client-side validation will save us round-trips back to the server.

So you have to write the logic on server-side… but serialization mechanisms serialize only data, not logic, so on the client-side you won’t have the validation logic that you implemented on server-side. That means that you have to duplicate your code and maintain the synchronization of validation logic between the client and the server manually.

Restrictions based on Authentication and Authorization

You support full CRUD and custom operations but maybe only authenticated users are capable of submitting an order or only administrators are allowed to delete or insert a new product. You want to define custom operations that can be executed only by certain users or by users in certain roles. Which means that you’ll have to implement authentication and authorization almost from scratch.

Introducing .NET RIA Services

As we discussed earlier, going N-Tier is inevitable but certainly necessary even if it means writing a lot of code. Fortunately, there is a technology called .Net RIA services that can help you out with these issues. .NET RIA Services can offer you out of the box solutions for the issues mentioned above.

If you install .NET RIA Services you’ll get new Silverlight application templates in Visual Studio. One of the new templates is the Silverlight Business Application template. This template generates a solution structure that provides a lot of functionality out of the box. If you run the empty project you’ll see that you have an application that supports navigation. You already have a home and an about page, it has a nice error window to display error messages (just try to navigate to a page that does not exist yet to see it) and it has a login and a register window as well. If you take a closer look at the project structure in the ASP.NET project you’ll see a Services folder where you can find prepared services for supporting user related operations like registration or login.

The structure of a DomainService

.NET RIA Services defines a class called DomainService which services as a base class to your Domain Services. A domain service contains different operations like CRUD or custom operations and is completely independent of the underlying layers. Let’s take a look at how a domain service implementation looks like:

 [EnableClientAccess()]
 public class SampleDomainService : DomainService
 {
     public IQueryable<Products> GetProducts()
     {
         return DataAccessLayer.ProductRepository.GetProducts();
     }
 }

Our SampleDomainService inherits from the DomainService abstract base class and it is decorated with the EnableClientAccessAttribute. This attribute means that the service will be visible from the client-side and static code generation will create the necessary client-side proxy objects.

Now we have a GetProducts method. The method returns an IQueryable<T> which means that this operation can be part of a more complex query. GetProducts will be the source of the complex query and any additional query methods can be appended to it. The actual implementation of the method could be anything. In this case it forwards the request to a custom data access layer. A “select” method must meet the following requirements:

  • returns IQuerable<T>, IEnumerable<T> or a singleton instance of type T
  • It should take 0 or more parameters
  • It may be decorated with the QueryAttribute to explicitly indicate the method as a query method

The structure of a Domain Context

Now if you build the project and you click show all files on the Silverlight Project you’ll get an [ApplicationName].Web.g.cs file in the Generated_Code folder. Let’s see what’s inside:

 public sealed partial class SampleDomainContext : DomainContext
 {
     public EntityList<Products> Products
    {
         get
         {
             return base.Entities.GetEntityList<Products>();
         }
     }
   
     public EntityQuery<Products> GetProductsQuery()
     {
         return base.CreateQuery<Products>("GetProducts", null, false, true);
     }
 ...

As you can see with static code generation without using Add Service Reference…, a DomainContext was created for you. Domain Context provides identity management, change tracking and operation invocation. This is the client context for your server-side domain service. You can compose complex queries using the GetProductsQuery method. As you can see it creates an EntityQuery that calls GetProducts on the server-side. The results of the query will be loaded into the exposed Products property of type EntityList<Product>. EntityList is a very friendly collection with rich data binding support.

So what happened? Static code generation happened based on conventions. We exposed a DomainService and defined a method that met some requirements in order to be identified as a query operation. A domain context was created on the client-side with access to our domain service and to our domain operation.

Writing a Simple Query using DomainContext

Now all you have to do is to create a query, run it and load the results into a DataGrid for example. Creating a query can be done in code-behind using a domain context instance:

 SampleDomainContext ctx = new SampleDomainContext();
  
 var query = from p in ctx.GetProductsQuery()
             where p.Discontinued == false
             select p;
  
 dataGrid.ItemsSource = ctx.Products;
 ctx.Load(query);

We used the GetProductsQuery() to serve as the source of the query composition. The DataGrid’s ItemsSource property is assigned to the domain context’s Products property of type Entity List which implements INotifyCollectionChanged so as soon as the data is loaded into the property it will be displayed on the UI.

Finally we have to explicitly call the Load method passing the composed EntityQuery as a parameter. This operation calls the domain service and fills up our local EntityList and of course it is done asynchronously.

Summary

In this introduction article we learned why using n-tier architecture is necessary and what kind of issues do we have to face. .NET RIA services aims to solve most of our problems using convention based static code generation. We got to know two important objects - the DomainService and the DomainContext.

Later we will see that more complex queries can be written and they can also be composed declaratively in XAML using a DomainDataSource object.


Subscribe

Comments

  • -_-

    RE: Building N-Tier business applications with .NET RIA Services – Part I


    posted by Jeff on Nov 05, 2009 21:47

    Thank you for the overview of RIA Services and showing its place in the n-tier structure.  A few questions:

    • When would you consider RIA Services production ready?
    • Over the intranet I believe I can use WCF's very fast tcp connections.  How does RIA Services compare?
    • In your example above, when you use LINQ to select from ctx.GetProductsQuery(), it appears that would return all columns from the Product table.  How would you go about only selecting particular columns?

    Thanks,

    Jeff

     

  • -_-

    RE: Building N-Tier business applications with .NET RIA Services – Part I


    posted by JAMBOO on Nov 06, 2009 02:54

    Please consider performance issues we are 9 month in to a RIA nTier app on silverlight and started using .Net Ria Services we had to roll back the full project because of performance problems. the same interfaces are as much as 6 times faster over WCF. YES  it is faster to develop and make a very nice RAD platform but I would wait until they get perfomance issues up o speed.

    iaburt@nexus-id.com

     

  • -_-

    RE: Building N-Tier business applications with .NET RIA Services – Part I


    posted by Zoltan Arvai on Nov 06, 2009 09:37

    Hi Jeff!

    I believe RIA Services will be production ready as soos as it goes RTM. I already use it in smaller projects but it definietly has downsides when it comes to performance requirements. WCF Tcp bindings is not available for RIA Service right now but it's built on the WCF platform. The team says later they will support many WCF bindings and configuration.

    You cannot say that you dont need the whole product. That is not supported. If you look at the structure you'll see that this would be a problem to implement. But you don't really need it. In a nice architecture you would use DTO-s (Data Transfer Object) and you would send only data back you'd want to work with on client-side. I will definetly write about it in this series.

     

    @JAMBOO

    I actually agree with you. However I believe the july preview is considerable stable (of course not over ADO.NET Data Service protocol) I wouldn't use it in preformance critic scenarios yet.

    We should not forget that RIA Services is in CTP right now.

     

  • -_-

    RE: Building N-Tier business applications with .NET RIA Services – Part I


    posted by Donald on Nov 07, 2009 17:21
    Should have just implemented DataSets. That would solve the concurrency problem, plus allow me to control the data both on the client and server as I can switch easily between the DataSet object and the xml diffgram.
  • -_-

    RE: Building N-Tier business applications with .NET RIA Services – Part I


    posted by Zoltan Arvai on Nov 09, 2009 17:31
    More and more we prefer to work with in OO manner. The concept of dataset is much closer to the relational world. Plus it's a heavyweight object.
  • -_-

    RE: Building N-Tier business applications with .NET RIA Services – Part I


    posted by Donald on Nov 10, 2009 05:46
    Heavyweight object?  I can have a single dataset, access 1000+ tables without the need to code it... that makes my DataSet object lightweight.  If I have to code 1000+ tables then I have a pretty big dll or 1000+ small dlls that I have to manage.
  • -_-

    RE: Building N-Tier business applications with .NET RIA Services – Part I


    posted by Zoltan Arvai on Nov 10, 2009 16:09

    Well DataSet is a heavyweight object. You really shouldn't use 1000+ tables in one database, but even if you do, someone will have to generate some code to make it work. Maybe that someone is your VS designer to generate those xsd schemas with all those adapters, it's really ugly. DataSets should stay in the data access layer and never leave the data tier. Binding directly to datasets is just bad practice. Sorry let me rephrase that, in complex scenarios - and by complex scenario I mean applications larger than simple demo applications - you should never use it directly.

    Besides serializing a DataSet to a diffgram is just enormous quantity of data.

    If you would use non typed datasets... well that not typesafe and binding would be really problematic, not to mention validation issues it would cause with the Silverlight validation framework. Fortunately there is no such object in Silverlight so it saves us from bad practice.

  • -_-

    RE: Building N-Tier business applications with .NET RIA Services – Part I


    posted by x on Nov 12, 2009 16:31
    Using Silverlight Ria Services, how can I automatically refresh my DataGrid in Silverlight side, if the database changed(eg new elem added)? Is there any easy to use way?
  • -_-

    RE: Building N-Tier business applications with .NET RIA Services – Part I


    posted by Zoltan Arvai on Nov 12, 2009 17:50

    Do you mean that if someone else changes the database? You can't. You can implement polling a service to get your data in periods but that will cause problems if you refresh a datagrid while you are working on it. So I would say after you submit the changes back by hitting a save button, solve any concurrency issues that may occure.

    If your datagrid is readonly and you have an acceptable time frame for simulating realtime updates, considering the number of clients and the server's hardver resources, you can poll your domain service.

  • -_-

    RE: Building N-Tier business applications with .NET RIA Services – Part I


    posted by Donald on Nov 13, 2009 03:53
    The code for the one data adaptor is fixed.  No need to generate schemas as they are generated automatically by the adaptor according to the select statement passed in.  We have services on the back end that are called according to a workflow script. These services are written once and well tested.  We've done strong type and non-type programming for the last 10 years. Our non-typed solutions wins everytime.  Saves time, coding, testing... etc.  And it's beautiful.  Sorry, to hear you think otherwise... however, I'm too surprised. Not everyone is good at writing "Software".
  • -_-

    RE: Building N-Tier business applications with .NET RIA Services – Part I


    posted by Zoltan Arvai on Nov 13, 2009 12:32

    "No need to generate schemas as they are generated automatically by the adaptor according to the select statement passed in. "

    This is exactly what I said. You won't have smaller code because if you use strongly typed datasets code will be generated.

    "Our non-typed solutions wins everytime.  Saves time, coding, testing... etc. And it's beautiful."

    Yeah, we really don't agree on the last sentence :) However your way is definetly is a way to go and I admit that sometimes non typed scenarios are more effective like dynamic types in C# 4.0.

    "however, I'm too surprised. Not everyone is good at writing "Software".

    Let me clear that. So basically you're saying that Brad Abrams, Nikhil Kothari, Tim Heuer, the guys at the patterns and practices team, the RIA team, the silverlight team, the ADO.NET team (who develop Entity Framework), most developers at Microsoft, and thousands of developers out there who agree on what I wrote above (actually I Agree with them, not the otherway around :D), and prefer n-Tier development with entity model classes and prefer not to use datasets on the presentation tier are not good at writing "Software"? I'm sorry you think so.

  • -_-

    RE: Building N-Tier business applications with .NET RIA Services – Part I


    posted by Donald on Nov 20, 2009 08:20

    More code if strongly typed, I agree. However, I'm not using strongly typed datasets and the generated schemas are at

    runtime. The code is small. It's not non-typed datasets, but rather meta-data defined type datasets.
    I can understand if you do not agree.. since the first few times I tried to go it.. it wasn't pretty. However, that

    never means it cannot be done.

    Excuse my poor attempt here to express my meaning, but I'll try: What I meant by Not Everyone is good at writing

    "Software" is this:

    Our company does outsourcing for another software company. The leader of that company told me if I could write

    software that someone could take and create hundreds of forms in a week, then my value would be more than that of one

    who only did 10 forms a week.
    If I wrote some code that was fixed and not easily changed such as:
    ds.Customers  then my code would actually be more like hardware, it's fixed. But if I did this:
    ds.Tables[someTableName]  then my code would be something someone else could reuse. This would be software.

    No, I'm not saying their not good at writing software... they are the brains behind the awesome DataSet. However,

    they dropped the ball in not carrying it over to Silverlight. Now they're trying to reinvent the wheel, but I do not see yet how it can be as flexible as the DataSet. Now others have to pick up the ball like DevExpress.

  • -_-

    RE: Building N-Tier business applications with .NET RIA Services – Part I


    posted by R on Nov 26, 2009 09:41

    I really liked the way you have explained it...

    I am looking for documentation which explains "How to use mulple clients against same server (DomainService)"? Please let me know if you are aware of some...

    R...

  • -_-

    RE: Building N-Tier business applications with .NET RIA Services – Part I


    posted by Sean on Dec 05, 2009 15:13

    Hi Zoltan, would you be adding Prism to your series? A lot of people have been blogging on the RIAServices, showing the new features. It will be nice if you could put in more particular use of different patterns with RIAService.

    thanks!

  • zoltan.arvai

    RE: Building N-Tier business applications with .NET RIA Services – Part I


    posted by zoltan.arvai on Dec 06, 2009 14:17

    R: What do you mean? With RIA Services you expose a service that can be used by multiple clients. Or you mean by the same instance?

    Sean: Honestly I haven't considered writing about Prism, most of the time simple MVVM and now MEF seems to be enough for me / us and I consider Prism a little heavyweight. But if Prism articles are wanted I'm definietly in, since for complex application development it is a key technology :)

  • -_-

    RE: Building N-Tier business applications with .NET RIA Services – Part I


    posted by zoltan.arvai on Jan 24, 2010 11:00

    Hi bobmar!

    When you configure your Profile in ASP.NET you can provide such things as application name. this property can be useful in situations like yours. So you waht you have to do is to configure your WCF config file and tell the profile porvider that the application name is the same as in your asp.net application.

    Something like this:

    <connectionStrings>
        <add name="myConnection" connectionString="......../>
      </connectionStrings>

      <system.web>
        <profile defaultProvider="myProvider">
          <providers>
            <add
              name="myProvider"
              type="System.Web.Profile.SqlProfileProvider" 
              connectionStringName="myconnection"
              applicationName="MyApplication" />
          </providers>

          <properties>
         ....... 
         </properties>
        </profile>
    .....

  • -_-

    RE: Building N-Tier business applications with .NET RIA Services – Part I


    posted by Sridhar on Jul 08, 2010 07:31

    Great article. Thanks.

    I am a beginner to .NET RIA Services and this article has helped me understand the basics.

     Cheers,

    Sridhar

Add Comment

Login to comment:
  *      *       

From this series