C# 实体框架核心在使用LINQ和谓词时不生成Where子句
错误标记重复-请参阅下面的答案 基本设置-我构建了一个应用程序上下文和一个抽象,用作DAO: 某些实体:C# 实体框架核心在使用LINQ和谓词时不生成Where子句,c#,sql,linq,.net-core,entity-framework-core,C#,Sql,Linq,.net Core,Entity Framework Core,错误标记重复-请参阅下面的答案 基本设置-我构建了一个应用程序上下文和一个抽象,用作DAO: 某些实体: public class SomeEntity { public string MyProp { get; set; } } DbContext: public class ApplicationContext : DbContext { public DbSet<SomeEntity> SomeEntities { get; set; } /* Res
public class SomeEntity
{
public string MyProp { get; set; }
}
DbContext:
public class ApplicationContext : DbContext
{
public DbSet<SomeEntity> SomeEntities { get; set; }
/* Rest of the DbContext doesn't matter. */
}
预期行为:
我希望EF Core生成如下SQL查询:
选择[e].MyProp
从[表名称]改为[e]
其中[e].MyProp='my string'
实际行为:
EF Core生成以下SQL查询:
SELECT [e].MyProp
FROM [TABLE_NAME] as [e]
它省略where子句,导致应用程序在筛选之前将每个记录都拉入内存
为什么?问题在于将
Func
传递给LINQ的Where
方法作为谓词。将Func
传递到Where
时,它返回一个IEnumerable
当您告诉EF Core返回一个IEnumerable
时,您告诉它的是您已经完成了对数据集的查询,并且想要枚举结果。因此,它在不使用适当的服务器端WHERE
子句的情况下生成一个查询,并立即拉入所有数据
不要接受Func
作为DAO类中的参数,而是接受表达式
,因为当您将表达式
传递给LINQ的方法时,它将返回IQueryable
而不是IEnumerable
。这有两个作用:
允许您在执行前向查询添加其他操作
告诉EF Core您希望在将结果集返回给应用程序之前过滤SQL中的记录
所以不是
public IEnumerable<SomeEntity> Where(Func<SomeEntity, bool> predicate)
{
return _dbSet.Where(predicate);
}
结果查询:
选择[e].MyProp
从[表名称]改为[e]
其中[e].MyProp='my string'
请注意,该方法的实现实际上根本没有改变,用法也没有改变-这是因为Func
和Expression
的某些形式是可互换的,在本例中使用其中一种形式不会导致编译错误,因此基本上是相同的
我通过几个小时的阅读找到了这个答案,最终在阅读后找到了答案。在此处重新发布一个与答案更为一致的问题,因为原始问题与问题无关。@GSerg-是-相关!谢谢你的推荐,希望我能在两天前找到!停止将其标记为要关闭或复制的内容-搜索“EF Core Missing Where子句”时不会弹出其他问题,这是为了能够被搜索到,而不是EF Core内部深处的某个模糊问题。这个主题并不新鲜,已经与和一起讨论过多次。我个人认为它不值得一个新的单独的自我回答的问题,你不这样认为,没有问题。你是说你自己的另一个问题涉及到这个问题,这将足以成为一个理由来同意这场势均力敌的投票。我们在这附近。以重复的方式结束问题不是惩罚。这个问题本身并没有被删除,可以很好地增加关键字的种类,使用这些关键字可以找到原始内容。这个问题不是EF Core特有的,它一直存在。我选择这个问题是因为它本身是另外两个问题的副本,方便地放在它的顶部:and,这很好地把你带到了。如果你只看Queryble.Where
(和其他Queryable
)扩展方法的签名,你会更快地找到答案Expression
vsFunc
是Queryable
和Enumerable
LINQ查询之间的根本区别。对于不愿意投资.NET isms的人来说,返回IQueryable vs IEnumerable的事实不足以让人们将其与不构建SQL查询联系起来。谢谢你的意见。
SELECT [e].MyProp
FROM [TABLE_NAME] as [e]
public IEnumerable<SomeEntity> Where(Func<SomeEntity, bool> predicate)
{
return _dbSet.Where(predicate);
}
public IEnumerable<SomeEntity> Where(Expression<Func<SomeEntity, bool>> predicate)
{
return _dbSet.Where(predicate);
}
Dao dao = new Dao(/* whatever for instantiation */);
var results = dao.Where(e => e.MyProp == "my string");