2009-09-21 51 views
2

我一直在少数项目上使用linq2sql,但我决定是时候尝试EF,因为它应该是更强大和更好。有几件事情真的很烦人。 其中之一是将结果投影到列表中,这在l2sql中效果很好,但在EF中效果不佳。entity-framework,如何投影到列表

public class bo.Transaction 
{ 
    public long Id { get; set; } 
    public List<bo.Line> Lines { get; set; } 
} 

public class bo.Line 
{ 
    public int RowNo { get; set; } 
    public string Descripton{ get; set; } 
    public double Amount{ get; set; } 
} 

return from t in Db.Transaction.Include("Lines") 
     select new bo.Transaction { 
     Id = t.Id, 
     Lines = t.Lines.OrderBy(l => l.RowNo).ToList(), 
     }; 

的ToList()调用但是失败,与消息“System.NotSupportedException:LINQ实体无法识别方法‘列表[bo.Line] ToListLine’方法,和这种方法不能被翻译成一家商店的表达。“”。

任何方法来解决这个问题?或者我只需要使用ienumerable而不是列表?

+0

一般来说,只要有可能,总是比较喜欢IList <>到List <>。 – 2009-09-21 13:48:23

回答

0

这是一个在黑暗中刺,但你的项目有一个System.Core DLL的参考?没有这个引用,.ToList()扩展方法将不可用。

此外,正如Workshop Alex指出的那样,您的.ToList()调用位置不正确。

+0

其不支持ToList()的EF转换器,引用是正确的 – AndreasN 2009-09-21 10:20:44

2
return (from t in Db.Transaction.Include("Lines") 
     select new bo.Transaction { 
     Id = t.Id, 
     Lines = t.Lines.OrderBy(l => l.RowNo), 
     }).ToList(); 

LINQ查询只是不支持列表中,所以我们执行这个在枚举结果。尽管如此,它确实会强制查询执行正确。返回IEnumerable会延迟查询的执行时间。 (基本上直到你要访问数据的那一刻。)

+1

“Include”在这里完全没有必要。因为你在投影,因此LINQ to Entities会为你排序。否则正确(+1) – 2009-09-21 13:46:25

0

写作Workshop Alex是正确的,但让我解释它背后的理论:
正如你可能知道的那样,当你编写一个LINQ-to -Entities查询,你正在写一些将针对你的数据库执行的东西。为了以一种有效的方式完成这项工作,我们不需要获取每个实体,按照给定的条件对其进行测试,对结果进行排序和这些操作,查询将被转换为SQL并针对您的数据库运行。
但是,事实上,您的查询接受任何有效的C#,并不意味着您可以编写的所有代码都具有对SQL的转换。没有翻译的代码的显着例子是一个混合数据访问和反射的实体类的查询,或者 - 就像你的情况一样 - 使用特殊的.NET数据类型的代码。这种查询通常可以分两步进行,一个针对数据库,另一个针对RAM中的实体。虽然这可能不会像你想要的那样高效和干净,但因为我个人不喜欢存储过程,所以我仍然发现它比其他大多数方法好得多,只要你的约束允许你做出选择。

编辑:
方案的确可以很容易地处理这种方式运行的数据库查询,并在内存部分的一部分:

 

Db.Transaction.Include("Lines").Select(t => new bo.Transaction { t.Id, Lines = t.Lines.OrderBy(l => l.RowNo) }).AsEnumerable().Select(t => new bo.Transacton { t.Id, Lines = t.Lines.ToList()}); 
 

的AsEnumerable呼叫有助于确保第二选择是针对已从数据库中获取的一组对象运行的,因此不再存在将ToList转换为SQL的问题。

+0

我很清楚linq查询的执行方式和时间。这不是问题在这里。 问题是我无法将子查询投影到其他对象的列表中。 它看起来比起在内存中执行部分查询更倾向于抛出运行时异常。 – AndreasN 2009-09-21 12:14:31

+0

这实际上是关于翻译和堆栈的哪一部分运行查询,因为您的问题实际上是您无法从LINQ查询中急切地获取集合,这是因为SQL实际上没有可调整大小的数组的线索。当然,你得到的异常并不是很清楚,但你必须考虑从你的查询生成的SQL不会在你的dbms的其他地方运行或验证,所以如果由于表达式生成了错误的SQL没有翻译,这是你将要得到的例外。 – em70 2009-09-21 13:33:10