是否可以通过实体框架核心中的连接列订购?
我有一个通过 EF Core 映射的关系数据库,其中包含一个自定义的多对多表,该表在映射旁边保存排序顺序。
精简示例类:
class A
{
int Id;
IEnumerable<AB> Bs;
DateTime Created;
}
class B
{
int Id;
IEnumerable<AB> As
}
class AB
{
int AId;
A A;
int BId;
B B;
int Ordering;
}
我想要获取 As 列表(为简洁起见,通过省略的某些条件进行过滤),然后按创建时间或连接表中指定的顺序进行排序。当按指定的 Ordering 属性进行排序时,结果将被过滤为仅链接到一个特定 B 的 As(尽管我认为这不会产生任何区别)。
所以我有类似的东西
_dbContext.As.Include(a => a.Bs)
.ThenInclude(ab => ab.B)
.Where( a => a.Bs.Any(b => b.Id == 1))
.OrderBy(a => a.Created)
.ToList()
,它返回所有链接到 ID 为 1 的 B 的 As,然后按其创建日期排序。
现在我想对链接到 B1 的所有 As 运行相同的查询,但按链接表中的排序进行排序。
在 SQL 中,这很简单,因为我知道我已经加入了链接表,并且可以仅按该列进行排序,但我找不到将其指定给实体框架的方法。
我可以将过滤后的 B Id 传递给子句,但这会为每一行构造一个 SQL 子查询,出于性能原因我想避免这种情况。
.OrderBy(a => a.Bs.First(ab => ab.BId == 1).Ordering)
我尝试将匿名类型传递给 OrderBy 子句,希望 EF 能够解释 Ordering作为加入的排序列,但事实并非如此。
.OrderBy(a => new {Ordering = 0}.Ordering)
我尝试从连接表开始,然后向外工作,当一个 A 链接到多个 B 时,这会导致重复问题,然后使用 Distinct 删除先前应用的排序。
_dbContext.ABs
.Include(ab => ab.A)
.Include(ab => ab.B)
.OrderBy(ab => ab.Ordering)
.Select(ab => ab.A)
.Distinct()
我尝试将 A 和 AB 表连接为匿名类型,以便我可以从连接表访问排序属性,但这也不起作用,重复数据删除也存在同样的问题。
_dbContext.As.Join( _dbContext.ABs, a => a.Id, ab => ab.AId, (a, ab) => new {a, ab})
.Where( x => x.ab.BId = 1)
.OrderBy( x => x.ab.Ordering)
.Select(x => x.A)
.Distinct()
我认为唯一的其他选择可能是将过滤后的数据具体化到内存中并在客户端上排序。但我想避免这种情况,因为我应该能够直接在生成的 SQL 中应用 ORDER BY。
有什么方法可以告诉实体框架按连接表中的排序列进行排序而不创建子查询?
I've got a relational database mapped via EF Core with a custom many to many table which holds a sort order alongside the mapping.
Stripped down example classes:
class A
{
int Id;
IEnumerable<AB> Bs;
DateTime Created;
}
class B
{
int Id;
IEnumerable<AB> As
}
class AB
{
int AId;
A A;
int BId;
B B;
int Ordering;
}
I want to get a list of As (filtered by some criteria omitted for brevity) and then ordered, either by the created time or by the ordering specified in the join table. When ordering by the specified Ordering property the results will be filtered to only As linked to one particular B (although I don't think that should make any difference).
So I have something like
_dbContext.As.Include(a => a.Bs)
.ThenInclude(ab => ab.B)
.Where( a => a.Bs.Any(b => b.Id == 1))
.OrderBy(a => a.Created)
.ToList()
which returns all As linked to B with Id 1, and then sorted by their created date.
Now I want to run the same query for all As linked to B1 but order by the Ordering from the link table.
In SQL it would be simple since I know I have joined on the link table and could just order by that column, but I can't find a way to specify that to Entity Framework.
I can pass the filtered B Id to the clause, but that constructs a SQL subquery for every single row, which I want to avoid for performance reasons
.OrderBy(a => a.Bs.First(ab => ab.BId == 1).Ordering)
I've tried passing an anonymous type to the OrderBy clause in the hope that EF would interpret Ordering as the joined Ordering column, but it didn't.
.OrderBy(a => new {Ordering = 0}.Ordering)
I've tried starting from the join table and working outwards instead, which then causes issues with duplication when one A is linked to multiple Bs, and using Distinct then removes the previously applied ordering.
_dbContext.ABs
.Include(ab => ab.A)
.Include(ab => ab.B)
.OrderBy(ab => ab.Ordering)
.Select(ab => ab.A)
.Distinct()
I've tried joining the A and AB tables into an anonymous type so that I have access to the ordering property from the join table, but that didn't work either, same issue with deduplication.
_dbContext.As.Join( _dbContext.ABs, a => a.Id, ab => ab.AId, (a, ab) => new {a, ab})
.Where( x => x.ab.BId = 1)
.OrderBy( x => x.ab.Ordering)
.Select(x => x.A)
.Distinct()
I think the only other option might be to materialise the filtered data into memory and sort on the client. But I want to avoid that when I should just be able to apply ORDER BY directly in the generated SQL.
Is there any way I can tell Entity Framework to order by the Ordering column in the join table without creating subqueries?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
尝试以下查询,我希望能理解您的问题。
Try the following query, I hope understand your question.