tags:

views:

54

answers:

2

Hi,

Depending on how I map my linq queries to my domain objects, I get the following error

The member 'member' has no supported translation to SQL.

This code causes the error:

public IQueryable<ShippingMethod> ShippingMethods {
    get {
        return from sm in _db.ShippingMethods
               select new ShippingMethod(
                   sm.ShippingMethodID, 
                   sm.Carrier,
                   sm.ServiceName, 
                   sm.RatePerUnit, 
                   sm.EstimatedDelivery, 
                   sm.DaysToDeliver, 
                   sm.BaseRate, 
                   sm.Enabled
                );
    }
}

This code works fine:

public IQueryable<ShippingMethod> ShippingMethods
{
    get
    {
        return from sm in _db.ShippingMethods
               select new ShippingMethod
               {
                   Id = sm.ShippingMethodID,
                   Carrier = sm.Carrier,
                   ServiceName = sm.ServiceName,
                   EstimatedDelivery = sm.EstimatedDelivery,
                   DaysToDeliver = sm.DaysToDeliver,
                   RatePerUnit = sm.RatePerUnit,
                   IsEnabled = sm.Enabled,
                   BaseRate = sm.BaseRate
               };
    }
}

This is my testmethod I am testing with:

[TestMethod]
public void Test_Shipping_Methods() {
    IOrderRepository orderRepo = new SqlOrderRepository();
    var items = orderRepo.ShippingMethods.Where(x => x.IsEnabled);
    Assert.IsTrue(items.Count() > 0);
}

How does the way in which I instantiate my object affect the linq to sql translation?

Thanks Ben

+2  A: 

It tries to map the entire linq query to SQL, including all method and property calls. The only exceptions are the object initializer syntax (both for anonymous as named types) and extension methods that themselves map to SQL (.Count() for instance).

Short story: you cannot use non-default constructors with Linq to SQL or Entity Framework.

Sander Rijken
What would I do in the case where I need to use a constructor? For example, I need to initialize the state of the object and this is done using an enum that is persisted to the database. Therefore, I need to pass this value into the constructor. Thanks
Ben
You can have a constructor, just not a constructor with parameters. Initialization should go in the parameterless (=default) constructor.
Sander Rijken
Okay, but I believe initializing using the object initializer syntax above hits the default constructor before the property values are assigned. So it seems if I need to initialize a state property based on one I am mapping above, I'm going to have to add some kind of initialize method and call this after the mapping has completed.
Ben
+1  A: 

The most significant issue here is that you are mixing predicate and projection semantics.

Once you project (i.e. with select), it is no longer safe to use the Where extension until you materialize the results with ToList(), ToArray() or similar. The second case just happens to work because the projection is completely transparent - all you are doing is property assignments, and to the same class. Constructors don't fall into this category; as the error message says, there's no equivalent representation of a constructor invocation in SQL Server.

Why do you need to do this projection anyway? The whole property could be replaced with just:

return _db.ShippingMethods.AsQueryable();
Aaronaught
It's probably not clear from my code but I am not using the Linq objects. So _db.ShippingMethods returns Linq.ShippingMethod but I am mapping to MyModel.ShippingMethod.Thanks for your explanation anyway.
Ben