以下代码有什么问题?
var results = db.Departments.Select(x => customfunction(x.DepartmentID));
results.toList();
答案 0 :(得分:4)
为什么这不会在编译时被捕获但在运行时会出现异常?
有许多不同的LINQ提供程序允许您对各种数据源使用LINQ(LINQ to Entities,LINQ to Objects,LINQ to XML等)。
虽然LINQ to Entities不知道如何调用自定义方法(至少不是公共数据库的提供程序),但某些LINQ提供程序可能很好地理解如何执行myfunction
。编译器未与所有LINQ提供程序集成,因此有关是否可以包含自定义方法的信息仅在运行时可用。
实际上,LINQ to Objects可以执行它
var results = db.Departments
.AsEnumerable()
.Select(x => myfunction(x.DepartmentID));
答案 1 :(得分:1)
的转换
db.Departments.Select(x => myfunction(x.DepartmentID));
到sql直到运行时的过程很晚才会发生。
所以在编译时,Entity Framework不知道myFunction不是什么,它不知道如何转换为sql。
当然可以做到
db.Departments.Select(x => (x * 2));
并且EF很乐意能够转换为sql但是如果你尝试在Departments对象上使用自定义属性而不映射到db中的字段或使用Linq数据提供者不知道的自定义方法如何翻译成sql你会得到同样的错误。
答案 2 :(得分:0)
这个想法很简单:.Select(x => myfunction(x.DepartmentID))
永远不会在C#中执行。相反,Entity Framework会解析此表达式并将其转换为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();
}