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)
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是围绕匿名对象设计的,您可以在上面选择它们.创建匿名对象时,将分配对象P和C被跟踪的对象,这意味着它们的关系会被记录,并且它们的状态由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)
| 归档时间: |
|
| 查看次数: |
29315 次 |
| 最近记录: |