views:

41

answers:

1

Just wondering if there is a way to take some of the repitition out of a LINQ to SQL projected type.

Example:

Table: Address

Fields: AddressID, HouseNumber, Street, City, State, Zip, +20 more

Class MyAddress: AddressID, HouseNumber, Street (Only 3 fields)

LINQ:

from a in db.Addresses
select new MyAddress
{
  AddressID = a.AddressID,
  HouseNumber = a.HouseNumber,
  Street = a.Street
}

The above query works perfectly, and I understand why something like this will return all 20+ fields in each row:

from a in db.Addresses
select new MyAddress(a);

class MyAddress
{
  public MyAddress(Address a)
  {
    this.AddressID = a.AddressID,
    this.HouseNumber = a.HouseNumber,
    this.Street = a.Street
  }
}

Which leads me to my Question:

Is it possible to implement some kind of helper function or extension method to "map" from the LINQ model to MyAddress yet only return the necessary fields in the query result rather than all of the fields?

+1  A: 
from a in db.Addresses
select new MyAddress
{
  AddressID = a.AddressID,
  HouseNumber = a.HouseNumber,
  Street = a.Street
}

That query will only select the requested fields in the resulting SQL.

A function to re-use the type will look like:

public IQueryable<MyAddress> ProjectAddress(IQueryable<Address> addresses)
{
    return from a in addresses
           select new MyAddress
           {
               AddressID = a.AddressID,
               HouseNumber = a.HouseNumber,
               Street = a.Street
           };
}

This can be used like this:

return ProjectAddress(db.Addresses);

I think a function would look something like:

public static Expression<Func<Address, MyAddress>> ToMyAddress()
{
    return a => new MyAddress { AddressID = a.AddressID, 
                                HouseNumber = a.HouseNumber,
                                Street = a.Street
                              };
}
SteadyEddi
It appears the key is IQueryable as the return type? How about for a single address? I have an object that has two properties: OriginalAddress and CurrentAddress, both of type address. Is it possible to create a helper function to accept the "domain model" and spit out a "view model", everything I try ends up pulling the entire record from the database. Am I attempting to refactor too much?
Mike
Using IQueryable means that the linq will remain an expression that can be built upon, that is later resolved into a query and executed. I think I understand what you are trying to achieve: represent the projection of the address entity into the address view model as code, and use that like a function call multiple times in another projection. Is that right?
SteadyEddi
The key will be to use dynamic linq and create an Expression that represents the transformation. IMHO I would say that the resulting code will look quite complicated to anyone unfamiliar with building Expressions and metaprogramming. It will definitely increase DRY value though. I would make a judgement call and say if I am repeating the code in a significant number of places, and changing that code will take a significant amount of time, then go for it.
SteadyEddi
I made an edit to the answer. Do you think its a step too far?
SteadyEddi