这为什么会在运行时间中捕获?

这为什么会在运行时间中捕获?

问题描述:

下面的代码有什么问题?这为什么会在运行时间中捕获?

var results = db.Departments.Select(x => customfunction(x.DepartmentID)); 
results.toList(); 

这是为什么这不是在编译时抓到,但给出了运行时异常?

有许多不同的LINQ提供程序允许您针对各种数据源(LINQ to Entities,LINQ to Objects,LINQ to XML等)使用LINQ。

虽然LINQ to Entities不知道如何调用自定义方法(至少不是公共数据库的提供者),但是一些LINQ提供者可能很好理解如何执行myfunction。编译器没有集成到所有的LINQ提供程序中,所以关于是否可以包含自定义方法的信息仅在运行时可用。

事实上,LINQ到对象可以执行它

var results = db.Departments 
       .AsEnumerable() 
       .Select(x => myfunction(x.DepartmentID)); 
+0

你能否详细说明吗?我还不明白..! –

+0

我更新了我的答案。 –

的的

db.Departments.Select(x => myfunction(x.DepartmentID)); 

到SQL转换不会发生,直到在运行过程中非常晚。

所以在编译时Entity Framework并不知道myFunction不是它不知道如何转换为sql的东西。

当然

你可以做

db.Departments.Select(x => (x * 2)); 

和EF会很乐意能够转换到SQL,但如果您尝试使用在部门对象的自定义属性不会映射到现场的分贝使用Linq数据提供者不知道如何转换为sql的自定义方法,您将得到相同的错误。

这个想法很简单:在C#中永远不会执行.Select(x => myfunction(x.DepartmentID))。相反,实体框架分析此表达式并将其转换为SQL。例如,如果您在C#中调用.Count(),EF会将其转换为SELECT COUNT(...)

这是非常强大的,除了少数情况下,例如您的情况。 EF通过Expression Trees分析您的代码。 如果在表达式树中调用myFunction(),则不可能“扩展”该调用以获取函数的主体。这是C#如何实现的限制。这就是为什么EF无法生成合理的SQL,因为它不知道你的方法是干什么的。

然而,有一个合理的选择:LinqKit

LinqKit将允许你写在你的表情可重复使用的“功能”。

例子:

static string[] QueryCustomers (Expression<Func<Purchase, bool>> purchaseCriteria) 
{ 
    var data = new MyDataContext(); 

    var query = from c in data.Customers.AsExpandable() 
       where c.Purchases.Any (purchaseCriteria.Compile()) 
       select c.Name; 

    return query.ToArray(); 
}