开发者

Workarounds for using custom methods/extension methods in LINQ to Entities

I have defined a GenericRepository class which does the db interaction.

 protected GenericRepository rep = new GenericRepository();

And in my BLL classes, I can query the db like:

public List<Album> GetVisibleAlbums(int accessLevel)
{
    return rep.Find<Album>(a => a.AccessLevel.BinaryAnd(accessLevel)).ToList();  
}  

BinaryAnd is an extension method which checks two int values bit by bit. e.g. AccessLevel=5 => AccessLevel.BinaryAnd(5) and AccessLevel.binaryAnd(1) both return true.

However I cannot use this extension method in my LINQ queries. I get a runtime error as follows:

LINQ to Entities does not recognize the开发者_如何转开发 method 'Boolean BinaryAnd(System.Object, System.Object)' method, and this method cannot be translated into a store expression.

Also tried changing it to a custom method but no luck. What are the workarounds?

Should I get all the albums and then iterate them through a foreach loop and pick those which match the AccessLevels?


I realize this already has an accepted answer, I just thought I'd post this in case someone wanted to try writing a LINQ expression interceptor.

So... here is what I did to make translatable custom extension methods: Code Sample

I don't believe this to be a finished solution, but it should hopefully provide a good starting point for anyone brave enough to see it through to completion.


You can only use the core extension methods and CLR methods defined for your EF provider when using Entity Framework and queries on IQueryable<T>. This is because the query is translated directly to SQL code and run on the server.

You can stream the entire collection (using .ToEnumerable()) then query this locally, or convert this to a method that is translatable directly to SQL by your provider.

That being said, basic bitwise operations are supported:

The bitwise AND, OR, NOT, and XOR operators are also mapped to canonical functions when the operand is a numeric type.

So, if you rewrite this to not use a method, and just do the bitwise operation on the value directly, it should work as needed. Try something like the following:

public List<Album> GetVisibleAlbums(int accessLevel)
{
    return rep.Find<Album>(a => (a.AccessLevel & accessLevel > 0)).ToList();  
}

(I'm not sure exactly how your current extension method works - the above would check to see if any of the flags come back true, which seems to match your statement...)


There are ways to change the linq query just before EF translates it to SQL, at that moment you'd have to translate your ''foreign'' method into a construct translatable by EF.

See an previous question of mine How to wrap Entity Framework to intercept the LINQ expression just before execution? and mine EFWrappableFields extension which does just this for wrapped fields.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜