Reader Level:
ARTICLE

Data Aggregation using Presentation Model in RIA and Silverlight 4

Posted by Manas Patnaik Articles | Silverlight with C# March 08, 2011
In-depth look into Presentation Model and its mode of handling related multiple entities.
  • 0
  • 0
  • 3976
Download Files:
 

My earlier post was about the basic CRUD operations on entities with relations. We had discussed about creating simple association and querying as well as Invoking CRUD operation onto them. As I have mentioned there, here in this article we will have an in-depth look into Presentation Model and it's mode of handling related multiple entities.

Introduction; What is Presentation Model??

The Presentation Model deals with data from more than one entities which are related to each other and projecting it as one entity.

We usually come across  situations where there is not a need to expose all the entities to the client side either for security reasons or else to avoid unnecessary code at client side. So instead of exposing everything as separate entities we can aggregate the data as a separate dummy to client or for presentation layer and can invoke operations onto it.

image_thumb.png

Case Study

Let's check a Data Model from AdventureWorksLT Database for online transactions. AdventureWorksLT is a sample SQL Server database from Microsoft. The following image shows the database schema.

AdventureWorksLTDetail_thumb.png

More details regarding the database can be found here. Also you can download database samples from codeplex with following links AdventureWorksLT 2005 Version, AdventureWorksLT 2008 Version. For Presentation model scenario I am going to use a part of the Data Model which involves Customer and Address.

image_thumb_3.png

Untill now normally we exposed Customer, CustomerAddress and Address to the client side as 3 separate entities and applied an association between them and then showed the results by joining them over by LINQ at client side. Instead of above procedure we will have a look into how to create a dummy entity and allowing only required combined property to the client side.

Setting Up the Project

The first steps involved here are to create a class for entity at server side project which will hold the custom properties we want to propagate. Let's name it CustomerPresentationModel.cs.

  1. public class CustomerPresentationModel
  2. {
  3. [Key]
  4. public int CustomerID { getset; }
  5. public string FirstName { getset; }
  6. public string LastName { getset; }
  7. public string EmailAddress { getset; }
  8. public string Phone { getset; }
  9. public string AddressLine1 { getset; }
  10. public string AddressLine2 { getset; }
  11. public string City { getset; }
  12. public string StateProvince { getset; }
  13. public string PostalCode { getset; }
  14. public int AddressID { getset; }
  15. public DateTime AddressModifiedDate { getset; }
  16. public DateTime CustomerModifiedDate { getset; }
  17. }


Well the basic step needs no elaboration, you can refer to my previous post for setting up a project using Entity Framework and RIA. Download the AdventureLT database and create a project as mentioned over my earlier articles. Add a domain service named ADVWORKDomainService with out selecting entity from the wizard.

image_thumb_4.png

Querying Data from Data Model

The first step involves adding a method that will return all the Customers with properties we want to expose. So create a method within the domainservice at server side project that will fetch the data from the Customer, CustomerAddress and Address entities and project it as CustomerPresentationModel.

  1. public IQueryable<CustomerPresentationModel> GetCustomersWithAddress()
  2. {
  3. return from c in this.ObjectContext.Customers
  4. join ca in this.ObjectContext.CustomerAddresses on c.CustomerID equals ca.CustomerID
  5. join a in this.ObjectContext.Addresses on ca.AddressID equals a.AddressID
  6. select new CustomerPresentationModel()
  7. {
  8. CustomerID = c.CustomerID,
  9. FirstName = c.FirstName,
  10. LastName = c.LastName,
  11. EmailAddress = c.EmailAddress,
  12. Phone = c.Phone,
  13. AddressLine1 = a.AddressLine1,
  14. AddressLine2 = a.AddressLine2,
  15. City = a.City,
  16. StateProvince = a.StateProvince,
  17. PostalCode = a.PostalCode,
  18. AddressID = a.AddressID,
  19. AddressModifiedDate = a.ModifiedDate,
  20. CustomerModifiedDate = c.ModifiedDate
  21. };
  22. }


Build the project and we can find the CustomerPresentationModel only is propagated to client side instead of all 3 separate entities.

image_thumb_5.png


SNAGHTML256221c_thumb.png

Execute this method asynchronously from Silverlight project and bind the result to data grid.

  1. private void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
  2. {
  3. biLoading.IsBusy = true;
  4. //Module lvel DomainContext
  5. cont=new ADVWORKDomainContext();
  6. //Call the Domain Service Method to fill the CustomerPresentationModel from 3 entities
  7. System.ServiceModel.DomainServices.Client.LoadOperation<CustomerPresentationModel> lp=
  8. cont.Load(cont.GetCustomersWithAddressQuery());
  9. //Attach OnCompleted Event handaler
  10. lp.Completed+=new EventHandler(lp_Completed);
  11. //Create Pagination for Grid
  12. System.Windows.Data.PagedCollectionView pagedcollview = new System.Windows.Data.PagedCollectionView(lp.Entities);
  13. dpCustomers.Source = pagedcollview;
  14. //Assign Paged Collection to the Grid
  15. dgCustomers.ItemsSource = pagedcollview;
  16. }


On executing the project we can find the result as follows.

image_thumb_6.png

Updating the Presentation Model

Until now we were able to fetch the data from the Data layer using a presentation model. Obiviously the next step involves updating the entities from the presented model from Silverlight page. So we need to add another method to domainservice class on server side to save the changes back to the model and database. Let's add a method with Update Attribute wrapper.

  1. [Update]
  2. public void UpdateCustomer(CustomerPresentationModel customerPM)
  3. {
  4. Customer customerEntity = this.ObjectContext.Customers.Where(c => c.CustomerID == customerPM.CustomerID).FirstOrDefault();
  5. CustomerAddress customerAddressEntity = this.ObjectContext.CustomerAddresses.Where(ca => ca.CustomerID == customerPM.CustomerID && ca.AddressID == customerPM.AddressID).FirstOrDefault();
  6. Address addressEntity = this.ObjectContext.Addresses.Where(a => a.AddressID == customerPM.AddressID).FirstOrDefault();
  7. customerEntity.FirstName = customerPM.FirstName;
  8. customerEntity.LastName = customerPM.LastName;
  9. customerEntity.EmailAddress = customerPM.EmailAddress;
  10. customerEntity.Phone = customerPM.Phone;
  11. addressEntity.AddressLine1 = customerPM.AddressLine1;
  12. addressEntity.AddressLine2 = customerPM.AddressLine2;
  13. addressEntity.City = customerPM.City;
  14. addressEntity.StateProvince = customerPM.StateProvince;
  15. addressEntity.PostalCode = customerPM.PostalCode;
  16. CustomerPresentationModel originalValues = this.ChangeSet.GetOriginal(customerPM);
  17. if (originalValues.FirstName != customerPM.FirstName ||
  18. originalValues.LastName != customerPM.LastName ||
  19. originalValues.EmailAddress != customerPM.EmailAddress ||
  20. originalValues.Phone != customerPM.Phone)
  21. {
  22. customerEntity.ModifiedDate = DateTime.Now;
  23. }
  24. if (originalValues.AddressLine1 != customerPM.AddressLine1 ||
  25. originalValues.AddressLine2 != customerPM.AddressLine2 ||
  26. originalValues.City != customerPM.City ||
  27. originalValues.StateProvince != customerPM.StateProvince ||
  28. originalValues.PostalCode != customerPM.PostalCode)
  29. {
  30. addressEntity.ModifiedDate = DateTime.Now;
  31. }
  32. this.ObjectContext.SaveChanges();
  33. }


The following piece of code of the method above creates 3 entities based on their ID.

  1. Customer customerEntity = this.ObjectContext.Customers.Where(c => c.CustomerID == customerPM.CustomerID).FirstOrDefault();
  2. CustomerAddress customerAddressEntity = this.ObjectContext.CustomerAddresses.Where(ca => ca.CustomerID == customerPM.CustomerID && ca.AddressID == customerPM.AddressID).FirstOrDefault();
  3. Address addressEntity = this.ObjectContext.Addresses.Where(a => a.AddressID == customerPM.AddressID).FirstOrDefault();


and then the next steps follows with assigning the changed values, followed by saving the changes.

Conclusion

Hence the Presentation Model are the Custom Entities built for the presentation layer instead directly the direct data model structure. As I used to say earlier the implementation is completely dependent on the scenario and security. Hope this article is detailed enough to explain how to start with presentation model. Keep suggesting Thumbs up .

erver'>
COMMENT USING

Trending up