实体框架中的可查询Linq查询差异

时间:2014-08-08 10:48:05

标签: c# sql linq entity-framework

我在实体框架中有一个非常简单的多对多表格,将我的批准连接到我的交易(如下所示)。

enter image description here

我正在尝试在审批对象内部进行查询,以计算审批中的交易金额,这应该相对容易。

如果我这样做,那么它的工作速度非常快。

int count;
EntitiesContainer dbContext = new EntitiesContainer ();

var aCnt = from a in dbContext.Approvals
        where a.id == id
        select a.Transactions.Count;

count = aCnt.First();

但是当我这样做时

count = Transactions.Count;

或者

count = Transactions.AsQueryable<Transaction>().Count();
它非常慢。我已经跟踪了在服务器上运行的sql,它确实似乎试图加载所有事务而不是仅仅对事务集合执行COUNT查询。

任何人都可以向我解释原因吗?

附加: 以下是EF模型对这两个类的看法

enter image description here

更新:

感谢所有回复,我相信我出错的地方是相信附加到Approval对象的集合将以IQueryable的形式执行。我将不得不对dbContext对象执行计数。

谢谢大家。

4 个答案:

答案 0 :(得分:5)

var aCnt = from a in dbContext.Approvals
    where a.id == id
    select a.Transactions.Count;

EF自行编译查询,上述查询将编译为select count个事务

不同
count = Transactions.AsQueryable<Transaction>().Count(); 
count = Transactions.Count;

这些将从事务中选择所有记录,然后计算计数

答案 1 :(得分:1)

您的第一种方法允许在数据库服务器级别进行计数。它会要求数据库不返回记录,而是返回找到的记录数量。这是最有效的方法。

这并不是说其他​​方法可以有效地工作,但是对于其他两行,您首先要说明的是您从Approvals上的联接中检索事务。相反,在另外两行中,您只需单独使用Transactions集合并对其进行计数,基本上强制集合被填充以便对其进行计数。

答案 2 :(得分:1)

当您访问a.Transactions属性时,则会加载事务列表(延迟加载)。如果您只想获得Count,请使用以下内容:

dbContext.Transactions.Where(t => t.Approvals.Any(ap => ap.Id == a.Id)).Count();

其中a获得批准。

答案 3 :(得分:1)

您的第一个代码段会导致在数据库服务器上执行查询。这是因为IQueryable实例是由实体框架提供的ObjectQuery类型,它执行必要的SQL转换然后执行。

第二个代码段说明如何使用IEnumerable个实例。在最坏的情况下,Count()通过枚举整个集合来处理它们。

在第三个代码段中,您尝试再次IEnumerable IQueryable。但是Enumerable.AsQueryable方法无法知道它正在IEnumerable得到了什么&#34;来了#34;来自实体框架。它能做的最好的事情是将IEnumerable包装在EnumerableQuery实例中,该实例只是动态编译给所有LINQ查询运算符的表达式树,并在内存中执行它们。

如果您需要由数据库服务器计算计数,您可以手动制定必需的查询(即,在代码段中编写已经执行的操作),或使用您可用的方法CreateSourceQuery如果你不使用Code First。请注意,它确实会在数据库服务器上执行,因此如果您修改了集合并且尚未保存更改,则结果将与通过直接调用Count返回的结果不同。