LINQ to Entities不支持LINQ表达式节点类型'Invoke' [英] The LINQ expression node type 'Invoke' is not supported in LINQ to Entities

查看:87
本文介绍了LINQ to Entities不支持LINQ表达式节点类型'Invoke'的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

public CategoryViewModel GetSingle( Expression<Func<CategoryViewModel, bool>> where)
        {
            Expression<Func<DAL.EntityModels.Category, CategoryViewModel>> converter =
                c => ToBll(c);

            var param = Expression.Parameter(typeof(DAL.EntityModels.Category), "category");
            var body = Expression.Invoke(where, Expression.Invoke(converter, param));
            var lambda = Expression.Lambda<Func<DAL.EntityModels.Category, bool>>(body, param);

            return  (CategoryViewModel )_categoryRepository.GetSingle(lambda);
}

代码 _categoryRepository.GetSingle(lambda)引发异常:"LINQ to Entities不支持LINQ表达式节点类型'Invoke'"

The code _categoryRepository.GetSingle(lambda) throws an exception: "The LINQ expression node type 'Invoke' is not supported in LINQ to Entities"

是否有简单方式来避免出现此异常?我不想使用其他工具,例如LinqKit或PredicateBuilder.

Is there easy way to avoid this exception? I don't want to use another tools like LinqKit or PredicateBuilder.

推荐答案

这涉及到Linq2Entities背后的一些问题以及Linq2Objects和Linq2AnythingElse之间的区别...

This gets into some of the plumbing behind Linq2Entities and the difference between Linq2Objects and Linq2AnythingElse...

您显然对表达式树有很好的理解,并且您正在以编程方式生成它们. Linq2Entities使用该表达式树,并尝试将其转换为SQL查询以在数据库服务器上运行.但是,它不能将任意C#代码映射到与其等效的SQL上(例如,toBll调用在SQL中绝对没有意义).

You obviously have a good understanding of expression trees and you're generating them programatically. Linq2Entities takes that expression tree and tries to convert it to a SQL query to run on the database server. However, It can't map arbitrary C# code onto its SQL equivalent (for example, the toBll call has absolutely no significance in SQL).

换句话说,您遇到了这个问题,因为Linq2Entities试图将您的toBll调用映射到SQL,并且失败了,因为没有这样的等效项.您尝试执行的操作中存在一些设计缺陷.我假设您正在尝试获取以"where"表示的任意条件,以便在数据库服务器上运行.但是,您的任意条件取决于您的业务层对象,并且SQL Server和实体框架都不了解这些对象.

In other words, you're hitting this problem because Linq2Entities is attempting to map your toBll call into SQL, and is failing miserably because there is no such equivalent. There is a bit of a design flaw in what you're trying to do. I'm assuming that you're trying to get the arbitrary condition expressed in "where" to run on the database server. However, your arbitrary condition is in terms of your business layer objects, and neither SQL server nor the entity framework know anything about these objects.

对于这种设计,您真正需要做的是用Linq2Entities类型而不是BLL类型表示任意条件.由于Linq2Entities知道这些类型,因此可以将任意表达式转换为SQL(因为它具有Linq2Entities类型到它们的SQL等效项的映射).

What you really need to do for this sort of design, is to have the arbitrary condition expressed in terms of the Linq2Entities types, not your BLL types. Since Linq2Entities knows about these types, it will be able to translate the arbitrary expression into SQL (since it has the mappings for the Linq2Entities types to their SQL equivalents).

我上面描述的确实是执行此操作的正确方法,或者,您可以枚举查询(将执行该查询),然后对返回的结果集运行条件.由于此时您正在Linq2Objects中运行(这只是针对内存中对象运行的标准.NET代码),因此您的函数将毫无问题地运行.但是,这意味着您的"where"子句将在内存中运行,而不是在数据库服务器上运行,因此我真的不建议这样做

What I described above is really the proper way to do this, alternatively, you could enumerate the query (which will execute) and then run the conditions against the returned result set. Since at this point you're running in Linq2Objects (which is just standard .NET code running against in-memory objects), your functions will run without issues. However, this means that your "where" clause will be run in-memory, and NOT on the database server, so I would really not recommend this

OP请求的代码...

OP requested code...

为使其正常工作,您需要更改GetSingle方法以采用对EntityFramework类型而非BLL类型起作用的表达式条件.然后,您可以从表达式树中删除converter子句,并且应该已经启动并运行:

In order for this to work properly, you need to change your GetSingle method to take an expression condition that acts on the EntityFramework type, and not on your BLL type. You can then remove your converter clause from the expression tree, and you should be up and running:

public CategoryViewModel GetSingle( Expression<Func<DAL.EntityModels.Category, bool>> where)
{

            var param = Expression.Parameter(typeof(DAL.EntityModels.Category), "category");
            var body = Expression.Invoke(where, param);
            var lambda = Expression.Lambda<Func<DAL.EntityModels.Category, bool>>(body, param);

            return  ToBLL((DAL.EntityModels.Category)_categoryRepository.GetSingle(lambda));
}

此方法的问题在于,您的表达式必须使用EntityFramework类型,这可能违反了隐藏数据抽象层细节的要求.那时,运气非常糟糕,EntityFramework + BLL +动态查询生成=难以正确完成

The problem with this approach is that your expression must be in terms of your EntityFramework type, which might violate your desire to hide the details of the data abstract layer. At that point, its pretty much tough luck, EntityFramework + BLL + Dynamic Query Generation = hard to get right

这篇关于LINQ to Entities不支持LINQ表达式节点类型'Invoke'的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆