【问题标题】:How do I construct a function that allows me to pass in several includes for EF via params?如何构造一个允许我通过参数为 EF 传递多个包含的函数?
【发布时间】:2020-09-16 14:58:13
【问题描述】:

我正在编写一个由 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 尽可能小而整洁。你有什么建议?它在断开连接的服务中使用,因此我不能依靠延迟加载来简单地获取更多数据(如果丢失)。获取数据后,我需要一次性获取数据,而第二次获取数据确实不切实际。

谢谢!

【问题讨论】:

  • 您似乎过于复杂化代码以使其动态化。你为什么不为每个返回的唯一数据集创建一个单独的方法?然后在需要时调用这些方法?
  • 答案很明显,我在这里找到了它:stackoverflow.com/questions/26619532/…
  • @CarlProthman 我不想在每次出现不同需求时都创建新方法。我喜欢尽可能使用框架功能。意图很明确,目标很简洁,所以我不认为这是一个问题,因为我不是在尝试制作一个上帝​​的方法。我觉得更有趣也有点尴尬,因为我没有想到“对象”是答案。哎……
  • 只是好奇。那么你必须有动态用户界面。因为如果您引入额外的子数据,您必须在 UI 中显示该数据。正确的?还是您正在做一些不同的事情,需要动态子行?
  • @CarlProthman 更多的是用于动态处理。大多数数据场景可以通过每次获取带来的一组核心表来满足。不过,有时我需要真正使用这些导航属性才能找到远处表格中的某些内容。就 repo 的交互方式而言,这些关联通常是非标准的。如果这些情况发生变化并变得普遍,我意识到最好对数据进行一些非规范化并简单地将其放入包含包中。

标签: c# .net entity-framework entity-framework-6


【解决方案1】:
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()

在这里找到答案:How to include 2 navigational properties in EF?

【讨论】:

  • 但是当您看到此 LINQ 的转换后的 SQL 时,上述包含始终显示内部连接。有没有一种方法可以使用相同的包含方法来实现左连接或右连接。作为参考,我包括我的帖子链接 stackoverflow.com/questions/55129505/...谢谢。
  • 起初这似乎是我的情况的解决方案,但是当我需要在上下文中进行实体跟踪时,我碰壁了。 DbSet.AsNoTracking 为需要跟踪的人排除了这种方法。
【解决方案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;
}

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-16
    • 1970-01-01
    • 1970-01-01
    • 2011-09-29
    • 2019-02-21
    • 1970-01-01
    • 2023-03-15
    • 2020-12-25
    相关资源
    最近更新 更多