1

I'm building a WPF application, using MVVM, and Prism. It's worth noting that I'm the only developer working on a large project, so resources are limited. Here's what I currently have:

  • Models - POCO's
  • ViewModels - contain instances of POCO's, and utilizes the service layer based on user interaction.
  • Views - bound to ViewModels
  • Services - WCF services for persistence, data retrieval

I'm using Dapper to map query results to my models.

I'm curious as to how others, that don't use an ORM, handle data retrieval given that myriad of variations if returning the fully loaded POCO object would cause a pretty significant query execution.

E.G.

public class Customer : BindableBase
{
   public string Name{ get; set; }
   public ObservableCollection<Address> Addresses { get; set; }
   public ObservableCollection<Contact> Contacts { get; set; }
}

public class Contact : BindableBase
{
   public ObservableCollection<PhoneNumber> PhoneNumbers { get; set; }
}

When looking at search results for Customers, we may only display Name. So a query like SELECT Name FROM dbo.Customer would suffice.

When editing a customer record, we need most of the data retrieved related to the Customer record, so there would be joins in the query to grab the addresses, contacts, and phone numbers.

... and there are umpteen other options, maybe they only need addresses, or just contacts.

The service layer will be used in other applications and technologies, and as such I'm going to have my business logic in there as a centralized location. Am I going to be stuck creating a function in the service layer to handle each scenario? E.G. GetSearchData(string searchCriteria) ... GetCustomerWithAddresses(int customerId) ... if so how would you go about structuring the project? I've read somewhere that another person has the service layer return the view model, which I'm not necessarily a fan of. I would still need the generic functions that return basic data for other technologies that consume the services.

1 Answer 1

1

Usually with a Customer object I would fully populate it. Although you want the possibility of multiple addresses etc you normally have only one or two and you tend to be dealing with a single customer at a time.

However, if you start having many sub objects or are dealing with many customers at a time (say for a report) I would remove all the sub objects (I usually use poco to mean only simple objects) and expose the relationships via the repository.

ie

repo.GetAddressesForCustomer(customerId)

class Address 
{
    string CustomerId {get;set;}
    ...
}

This allows you to, limit your returned data to only that which is needed and also to optimise your queries for the specific dataset you want to retrieve.

Say for example we want to show a list of customers with active orders, showing id, name and postcode of primary address.

Loading the full object one by one would entail n+1 db queries, even if we lazy load via EF or some other clever ORM we could end up with an inefficient query with wierd joins. But if we retain control at the repository layer we can populate our view model with

repo.GetCustomersWithActiveOrders();
repo.GetPrimaryAddressesOfCustomersWithActiveOrders();
2
  • I did something similar in the past... each POCO had a related repository with basic CRUD functions and the ViewModel would be responsible for determining whats pulled and associated the results together. I did this in the past through a data access class library. With this project I definitely need to expose it through services... and would like to limit the amount of round trips to the services layer if possible.... implications may be negligible... not sure yet. Commented Oct 2, 2015 at 14:08
  • I guess the more you optimise to reduce the number of requests the closer you get to returning the viewmodel
    – Ewan
    Commented Oct 2, 2015 at 14:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.