我如何构建一个函数,允许我通过参数传递EF的几个包含



我正在编写一个ef支持的存储库,该存储库具有与每个实体类型相关联的包的概念,这些实体类型为其常用的子实体提供. include。例如,我有一个像这样的函数

private static IQueryable<Foo> GetFooPackage(Entities context)
{
    return context.Foo
        .Include(target => target.Bar)
        .Include(target => target.FooBar)
}

这就是当我运行我的"get"方法时,返回的数据有一个一致的分组。然而,我希望能够在具体案例的基础上进行扩展。我希望能够做一些像

这样的事情
public static Foo GetFoo(int fooId, params Expression<Func<Foo, T>>[] extraIncludes)
{
    using (Entities context = GetContext(null))
    {
        IQueryable<Foo> package = GetFooPackage(context);
        extraIncludes.ToList().ForEach(expression => package.Include(expression));
        return package.FirstOrDefault(target => target.FooId == fooId);
    }
}

让我失望的是T部分。我知道这个例子没有正确地引用T泛型。它只是示例的占位符。我不确定如何塑造它,这样我才能做我想做的事。最终,这是为了使EF生成的SQL尽可能小而简洁。你有什么建议吗?它是在一个断开连接的服务中使用的,所以我不能依靠延迟加载来简单地获取更多的数据,如果它丢失了。一旦我获取了数据,我需要一次获取它,而进行第二次获取实际上是不现实的。

谢谢!

public IQueryable<T> GetAllIncluding(params Expression<Func<T, object>>[] includes)
{
    var query = DbSet.AsNoTracking();
    query = includes.Aggregate(query, (current, includeProperty) => current.Include(includeProperty));
    return query;
}
MyGenericRepository<A>().GetAllIncluding(x=> x.B, x=> x.C).FirstOrDefault()

在这里找到答案:如何在EF中包含2个导航属性?

对于那些由于DbSet.AsNoTracking而无法使用公认答案的人,这里有一个替代方案:

public IEnumerable<TEntity> Retrieve(params Expression<Func<TEntity, object>>[] relations)
{
    IQueryable<TEntity> query = this.Entities;
    foreach (var relation in relations)
        query = query.Include(relation);
    return query;
}

该版本循环遍历关系数组,并在每次迭代时展开查询。

最新更新