Linq To SQL FirstOrDefault获取所有行

时间:2013-11-28 16:59:01

标签: sql entity-framework linq-to-sql

我正在创建一个通用存储库,而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);
    }
}

1 个答案:

答案 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

参考文献:

Why would you use Expression<Func<T>> rather than Func<T>?

Re-implementing Linq-To_Objects - AsEmumerable()