This post is a follow-up to an article I wrote a few weeks ago, ADO.NET Entity Framework Comparison Frustration. As a quick re-cap, I was simply trying to filter a list of users with a LINQ query expression by comparing custom classes, not primitive types.

TorvusEntities entities = new TorvusEntities(); 

// Pull my Account Entity from the database
Account matt = entities.Accounts.First(a => a.AccountId == 10);

// Attempt to get all Teams by a Team Owner
var teams = from t in entities.Teams
                 where t.Owner == matt
                 select t;

However, an exception was thrown.

Unable to create a constant value of type 'Closure type'. Only primitive types (for instance Int32, String and Guid) are supported in this context.

So I left it at that. The Entity Framework could only handle comparison on primitive types, which makes sense of course, since the expression needs to be converted into the underlying data storage language (T-SQL in this case). I was simply hoping that they would provide a more object-oriented way of translating the comparison I hoped to express by some other means. E.g., overriding Object.Equals() or the == operator, implementing a certain interface on my entities, something that felt OO to me.

Today however, I found my answer. Embarrassingly enough, it was in the MSDN docs all along.

A comparison expression checks whether a constant value, property value, or method result is equal, not equal, greater than, or less than another value. If a particular comparison is not valid for LINQ to Entities, an exception will be thrown. [Specifically, the exception I wrote above.] All comparisons, both implicit and explicit, require that all components are comparable in the data store. Comparison expressions are often used in Where clauses for restricting the query results.

And here it is, the confirmation I wanted (albeit not the answer I was hoping for):

LINQ to Entities does not support using a user class as a constant. However, a property reference on a user class is considered a constant, and will be converted to a command tree constant expression and executed on the data store.

Oh, another thing worth mentioning, method returns don't count as so-called constant expressions, and will thrown an exception when attempted.

public class MyBusinessObject
{
    public int GetId()
    {
        return 5;
    }
}

public class Test
{
    public Test()
    {
        using (TorvusEntities context = new TorvusEntities())
        {
            MyBusinessObject myBo = new MyBusinessObject();
            var accounts = from a in context.Accounts
                           where a.AccountId == myBo.GetId()
                           select a;

            // Exception will be thrown at run-time,
            // methods do not count as Constant expressions
        }
    }
}
Technorati Tags: ,

Comments

# re: Entity Framework Comparison Frustration: Explained

Gravatar
evanj
6/29/2009 1:42 PM
thanks this was really helpful!

# re: Entity Framework Comparison Frustration: Explained

Gravatar
poker game online guide
7/17/2009 3:28 AM
Nice post. I share your opinions that ADO.NET DS is good, but EF not that much.

# 

Gravatar
Giovanni Montrone's Blog
8/16/2009 1:37 AM
Problem with casting enums in LINQ to Entities

# re: Entity Framework Comparison Frustration: Explained

Gravatar
Wheelzzz
11/16/2009 4:13 PM
Wow. This simple explanation really helped me. Of course Linq has trouble with o.object == myobject. It gets converted to SQL.

Thanks!

# re: Entity Framework Comparison Frustration: Explained

Gravatar
Yann
1/21/2010 8:39 PM
Hi Matt,

There IS a way to do what you were trying to do. Assuming that the entity you're trying to use has a property call ID, instead of

"where t.Owner == matt"

just use

"where t.Owner.ID == matt.ID"

If your object doesn't have an ID property, surely it would have some other unique identifier, so you would use that in place of ID.

Hope that helps,

Yann
Post Comment
Title *  
Name *  
Email
URL
Comment *  
Please add 2 and 8 and type the answer here: