Kyl*_* L. 1 c# sql linq entity-framework-core .net-core
错误地标记为重复 - 请参阅下面的答案
基本设置 - 我有一个应用程序上下文和一个用作 DAO 的抽象:
某个实体:
public class SomeEntity
{
public string MyProp { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
数据库上下文:
public class ApplicationContext : DbContext
{
public DbSet<SomeEntity> SomeEntities { get; set; }
/* Rest of the DbContext doesn't matter. */
}
Run Code Online (Sandbox Code Playgroud)
道:
public class DAO
{
private readonly DbSet<SomeEntity> _dbSet;
public DAO(ApplicationContext context)
{
_dbSet = context.SomeEntities;
}
public IEnumerable<SomeEntity> Where(Func<SomeEntity, bool> predicate)
{
return _dbSet.Where(predicate);
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
Dao dao = new Dao(/* whatever for instantiation */);
var results = dao.Where(e => e.MyProp == "my string");
Run Code Online (Sandbox Code Playgroud)
预期行为:我希望 EF Core 生成如下 SQL 查询:
public class SomeEntity
{
public string MyProp { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
实际行为:EF Core 生成以下 SQL 查询:
SELECT [e].MyProp
FROM [TABLE_NAME] as [e]
Run Code Online (Sandbox Code Playgroud)
它省略了 where 子句,导致应用程序在过滤之前将每个记录拉入内存。
为什么?
问题在于您将Func<SomeEntity, bool>LINQ 的Where方法作为谓词传递。当您将 a 传递Func给它时Where,它会返回一个IEnumerable.
当您告诉 EF Core 返回一个IEnumerable信息时,您所传达的意思是您已完成数据集查询并想要枚举结果。因此,它会生成一个没有适当服务器端子WHERE句的查询,并立即提取所有数据。
不要Func在 DAO 类中接受 a 作为参数,而是接受 an Expression<Func<SomeEntity, bool>>,因为当您将 an 传递Expression给 LINQ 的Where方法时,它将返回一个IQueryable而不是一个IEnumerable。这有两件事:
所以而不是
public IEnumerable<SomeEntity> Where(Func<SomeEntity, bool> predicate)
{
return _dbSet.Where(predicate);
}
Run Code Online (Sandbox Code Playgroud)
它应该是
public IEnumerable<SomeEntity> Where(Expression<Func<SomeEntity, bool>> predicate)
{
return _dbSet.Where(predicate);
}
Run Code Online (Sandbox Code Playgroud)
用法:
Dao dao = new Dao(/* whatever for instantiation */);
var results = dao.Where(e => e.MyProp == "my string");
Run Code Online (Sandbox Code Playgroud)
查询结果:
public IEnumerable<SomeEntity> Where(Func<SomeEntity, bool> predicate)
{
return _dbSet.Where(predicate);
}
Run Code Online (Sandbox Code Playgroud)
请注意该方法的实现实际上根本没有改变,用法也没有改变 - 这是因为Func和的某些形式Expression是可以互换的,在这种情况下使用其中之一不会导致编译错误,因此基本上是相同的。
我通过长时间浏览 SO 帖子找到了这个答案,并在阅读/sf/answers/2937366631/后终于找到了答案。由于原始问题与该问题无关,因此在此处重新发布一个与答案更一致的问题。
| 归档时间: |
|
| 查看次数: |
1251 次 |
| 最近记录: |