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

C#EF 6.1-带委托的条件查询的Strage行为,c#,sql-server,entity-framework,C#,Sql Server,Entity Framework,我注意到实体框架6.1的一个非常奇怪的行为。我的目标是有条件地从一个充满200万条记录的表中计算一些行。首先,我使用了简单的方法来获得所需的值: private void SeedsQuery(object o) { StatProperty property = o as StatProperty; using (SteelPoppyContext context = new SteelPoppyContext()) { property.Va

我注意到实体框架6.1的一个非常奇怪的行为。我的目标是有条件地从一个充满200万条记录的表中计算一些行。首先,我使用了简单的方法来获得所需的值:

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);
    }
}
private void SeedsQuery(对象o)
{
StatProperty属性=o作为StatProperty;
Func谓词=新Func(game=>game.IsSeed);
使用(SteelPoppyContext上下文=新的SteelPoppyContext())
{
property.Value=context.QueuedGames.Count(谓词);
}
}
此方法应与上面的方法完全相同。但是,当我运行这段代码时,查询执行大约需要1分钟,使用的内存会跳到1GB。我猜实体框架正在从数据库获取所有数据,然后检查条件。对这种行为有什么解释吗

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

其实一点也不。您编写的方法与您原来的代码不同

您的原始代码使用的重载采用的是
表达式,而不是
Func
。因此,如果要编写等效代码,请确保:

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);
    }
}
private void SeedsQuery(对象o)
{
StatProperty属性=o作为StatProperty;
表达式谓词=x=>x.IsSeed;
使用(SteelPoppyContext上下文=新的SteelPoppyContext())
{
property.Value=context.QueuedGames.Count(谓词);
}
}
请注意,我在示例中使用的
谓词
变量是一个
表达式
,而不仅仅是一个
Func


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

EF使用表达式树将C代码转换为SQL,正如Darin指出的,您没有在委托中使用表达式,因此EF相当于.AsEnumerable()以便将其转换为非表达式。