C#EF 6.1 - 带委托的条件查询的存储行为

时间:2015-02-14 22:54:36

标签: c# sql-server entity-framework

我注意到Entity Framework 6.1的一个非常奇怪的行为。我的目标是有条件地从填充了2百万条记录的表中计算一些行。首先,我已经使用简单的方法来获得所需的值:

private void SeedsQuery(object o)
{
    StatProperty property = o as StatProperty;

    using (SteelPoppyContext context = new SteelPoppyContext())
    {
            property.Value = context.QueuedGames.Count(game => game.IsSeed);
    }
}

此代码运行大约1秒,无需使用任何内存即可提供所需的结果。现在,我想使用switch语句为同一个查询实现更多条件。最简单的方法是使用每次运行查询时提供的委托。为了简化我们的案例,我准备了一个简单的例子。

private void SeedsQuery(object o)
{
    StatProperty property = o as StatProperty;
    Func<QueuedGame, bool> predicate = new Func<QueuedGame, bool>(game => game.IsSeed);

    using (SteelPoppyContext context = new SteelPoppyContext())
    {
            property.Value = context.QueuedGames.Count(predicate);
    }
}

此方法应与上面的方法完全相同。但是,当我运行此代码时,查询执行大约需要1分钟,并使用内存跳转到1GB。我猜测实体框架正在从数据库中获取所有数据,然后检查条件。这种行为有什么解释吗?

1 个答案:

答案 0 :(得分:6)

  

此方法应该与上面的方法完全相同

实际上根本没有。您编写的方法与您原来的代码不同。

您的原始代码使用的是Count重载Expression<Func<T, bool>>而不是Func<T, bool>。因此,如果您想编写等效代码,请确保执行此操作:

private void SeedsQuery(object o)
{
    StatProperty property = o as StatProperty;
    Expression<Func<QueuedGame, bool>> predicate = x => x.IsSeed;

    using (SteelPoppyContext context = new SteelPoppyContext())
    {
            property.Value = context.QueuedGames.Count(predicate);
    }
}

请注意,我在示例中使用的predicate变量是Expression<Func<QueuedGame, bool>>,而不仅仅是Func<QueuedGame, bool>

现在,EF将能够构建正确的SQL,而不是将整个表加载到内存中,然后在浪费所有内容后计算记录。