为什么这会陷入运行时间?

时间:2015-05-11 22:28:49

标签: c# asp.net-mvc linq entity-framework

以下代码有什么问题?

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

3 个答案:

答案 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();
}