views:

119

answers:

3

Let's say I need to display a list of customers, but only want to display the Name and somehow associate the key to the name within a list control.

It would probably be costly to retrieve the entire list of customers and all it's properties. In this scenario, would it be better to create another class with the properties that are required (in this case Id and Name)?

A basic implementation could look like this:

public class Customer {
    public int Id { get; set; }
    public string Firstname { get; set; }
    public string Lastname { get; set; }
    public int Age { get; set; }
    .....
}

public class CustomerListView {
    public int Id { get; set; }
    public string Name { get; set; }
}

public interface IRepository<T> {
    public T Find(int id);
    public IEnumerable<T> FindAll();
    ....
}

public class Repository<T>: IRepository<T> {
    ....
}

public class CustomerRepository: Repository<Customer> {
    public IEnumerable<CustomerListView> FindAllListView();
}

Would this approach be appropriate? What other options would there be?

+1  A: 

If you use IQueryable as your return instead of IEnumerable than there is no cost of doing:

CustomerRepository().GetAll().Find(1) because AsQueryable doesn't actually execute until you request data. That means LINQ can optimize it out to a:

SELECT .... FROM .... WHERE ID = 1 instead of

GET EVERYTHING. FIND WHERE THE ID = 1

See this post for an explanation:

http://stackoverflow.com/questions/1106802/why-use-asqueryable-instead-of-list

Using this approach you could create an anonymous class and futher narrow down the data going over the wire to just what you want. That way the query generated by LINQ is optimized to the fullest.

Nissan Fan
This is an interesting idea, which I had not considered. Aside from coupling my repository to LINQ, are there other reasons to avoid this? I had always assumed the repository's responsability was to provide access to domain objects. Either way, I will look into this suggestion since I don't mind deviating from 'pure' DDD if I have to.
Joepro
LINQ is a core feature of C# so no concern. This design pattern is often seen as Repository, but it's more ActiveRecord than anything. What I do often is use the Decorator Pattern and put extension methods off types to do further filtering.
Nissan Fan
+2  A: 

In order to achieve such goals, I create a simple 'View' class, for example CustomerView, which just contains the properties that are needed to display an overview.

My Repository then has a method which returns a collection of these CustomerView objects.

I mostly use NHibernate in my projects. Nhibernate allows you to use 'projections'. So, what I do in my repository is this: (note that the code below is just some pseudo-code; it won't compile).

public IList<CustomerView> GetAllCustomers()
{
    ICriteria crit = _session.CreateCriteria (typeof(Customer));

    crit.AddProjection ( ... );

    crit.SetResultTransformer (new EntityToBeanTransformer(typeof(CustomerView));

    return crit.ToList();
}

In fact, it comes down to this: I tell my O/R mapper that it should query Customers, but that it should return entities of type 'CustomerView'. In the defintion of the projection, I also define which properties of the Customer class map to which properties of the CustomerView class. Then, the O/R mapper is smart enough to generate a very simple query, which only retrieves those fields that are required to populate the CustomerView class. For instance, the query that is executed can be as simple as:

SELECT customerid, customername FROM tblCustomer
Frederik Gheysels
I hadn't considered using NHibernate. Thanks for the suggestion.
Joepro
My point was not really to suggest you should use NHibernate (although it would help, as it is a fine tool), but more that it is -imho- perfectly valid to use a 'dumb' CustomerView type in order to display an overview of Customers.
Frederik Gheysels
A: 

You could combine the techniques used by Nissan and Frederik (anonymous types and NHibernate) by using Linq-to-NHibernate.

Item #31 in Bill Wagner's More Effective C# says "limit type scope by using anonymous types", and I agree. BTW, I recommend the whole book.

Martin R-L