实体框架使用排序顺序加载子集合

X18*_*181 31 entity-framework poco code-first ef-code-first

我有两个表父表和子表.子表具有列排序顺序(数值).由于缺少EF的支持来持久化IList包含排序顺序而不暴露排序顺序(请参阅:实体框架持久化子集合排序顺序)我的子类还有一个属性SortOrder,因此我可以存储具有排序的子项订购.

与引用问题的autor相反,我尝试加载始终排序的子项.因此,如果我加载一个我期望的父实例,那么子集合按排序顺序排序.如何使用Code First Fluent API和POCO实现此行为?

提示:在子集合上调用.Sort(...)不是一个选项.

Lad*_*nka 39

您无法直接实现它,因为EF中的急切或延迟加载都不支持排序或过滤.

你的选择是:

  • 从数据库加载数据后,对应用程序中的数据进行排序
  • 执行单独的查询以加载子记录.使用单独的查询后即可使用OrderBy

第二个选项可以与显式加载一起使用:

var parent = context.Parents.First(...);
var entry = context.Entry(parent);
entry.Collection(e => e.Children)
     .Query()
     .OrderBy(c => c.SortOrder)
     .Load();
Run Code Online (Sandbox Code Playgroud)

  • 不要忘记添加:using system.data.entity和system.linq的语句 (2认同)

Chr*_*ini 28

您可以在单个查询中有效地执行此操作,语法只是尴尬:

var groups = await db.Parents
    .Where(p => p.Id == id)
    .Select(p => new
        {
            P = p,
            C = p.Children.OrderBy(c => c.SortIndex)
        })
    .ToArrayAsync();

// Query/db interaction is over, now grab what we wanted from what was fetched

var model = groups
    .Select(g => g.P)
    .FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)

说明

异步备注

我碰巧在async这里使用了你可能应该使用的扩展,但你可以摆脱await/ async如果你需要一个同步查询而不会损害有效的子排序.

第一块

默认情况下,从Db获取的所有EF对象都被"跟踪".此外,EF的等效于SQL Select是围绕匿名对象设计的,您可以在上面选择它们.创建匿名对象时,将分配对象PC被跟踪的对象,这意味着它们的关系会被记录,并且它们的状态由EF更改跟踪器维护.由于C是子列表P,即使您没有要求它们在您的匿名对象中明确相关,因此EF无论如何都将它们加载为此子集合,因为它在架构中看到的关系.

要了解更多信息,您可以将上述内容分解为两个单独的查询,在完全不同的Db调用中仅加载父对象,然后只加载子列表.EF Change Tracker将注意到并将子项加载到父对象中.

第二块

我们欺骗EF回归有序的孩子们.现在我们只抓住Parent对象 - 它的子节点仍然按照我们想要的顺序连接.

空集和表作为集

这里有一个尴尬的两步,主要是针对零点的最佳实践; 它可以做两件事:

  • 将数据库中的内容想象为设置,直到可能的绝对最后时刻.

  • 避免空例外.

换句话说,最后一个块可能是:

var model = groups.First().P;
Run Code Online (Sandbox Code Playgroud)

但是如果数据库中没有该对象,则会以空引用异常爆炸.C#6将引入另一个替代方案,即null属性合并运算符 - 所以将来你可以用以下代码替换最后一个块:

var model = groups.FirstOrDefault()?.P;
Run Code Online (Sandbox Code Playgroud)

  • 有谁知道这是否适用于EF7?它不适合我,我猜这就是原因. (4认同)
  • 这对我有用!多么棒的黑客!经过几个相关的问题,终于有一个有效的好答案!X181 应该将此标记为正确答案,IMO。 (2认同)
  • @vtortola 添加了更多解释以试图解释这里发生的事情,希望它有所帮助。 (2认同)