我正在创建一个通用存储库,而FirstOrDefault没有生成我期望的sql查询。
您可以在下面看到相关部分。例如,如果我使用“.Find(x => x.Id == id);”在使用此repo的表上,生成的sql首先获取所有行并执行firstordefault操作。我希望它在哪里生成一个where子句。
关于我做错了什么的任何想法?
public class Repo<T> : IRepo<T> where T : class
{
protected SBContext Context { get; set; }
public Repo(SBContext context)
{
Context = context;
}
protected DbSet<T> DbSet
{
get
{
return Context.Set<T>();
}
}
public T Find(Func<T, bool> predicate)
{
return DbSet.FirstOrDefault(predicate);
}
}
答案 0 :(得分:3)
尝试将方法签名更改为
public T Find(Expression<Func<T, Boolean>> predicate)
说明:
在System.Linq.Queryable
中,有一个带有此签名的扩展方法:
public static TSource FirstOrDefault<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate);
并且在System.Linq.Enumerable
中,有一个带有此签名的扩展方法:
public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);
当您指定Find方法采用Func
时,您使用的是Enumerable
扩展名而不是Queryable
扩展名。
当IEnumerable<TSource>
作为IQueryable Context.Set<T>()
参数传递给source
时,以及IQueryable
投放到IEnumerable
时,会隐含强制转换为{{1}}表达式立即被评估并对数据库运行,数据被拉入内存,你现在正在使用Linq-to-Objects
参考文献: