我使用asp.net core 1.1和mvc遇到了我的应用程序问题。据我所知,在执行查询时,在将orderby,skip / take和查询组合在一个包含的表上时,我得到的结果不正确。
架构很简单。
public Class Member
{
public int Id {get; set;}
public int Family {get; set;}
public bool IsMember {get; set;}
public DateTime DeceasedDate {get; set;}
...
public int LivesWithId {get; set;}
public Member LivesWith {get; set;}
public ICollection<Member> LivingWith {get; set;}
}
缺点是,你是否有一个人与一个家庭,其他人可以与这个人住在一起。标准的一对一。
我跑步的c#代码看起来相对简单......它发现任何一个成员或者与他们一起生活的人都没有去世。这不是一个非常好的查询,它有点慢,但就我的目的来说,它应该足够好了。它确实有效,直到我进入skip / take。
var q = _context.Members.Include(m => m.LivingWith).AsQueryable();
q = q.Where(m => m.IsMember || m.LivingWith.Count(s => s.DeceasedDate == null) > 0);
q = q.OrderBy(m => m.Family);
q = q.Skip(100);
q = q.Take(100);
var result = await q.ToListAsync();
实体框架采用此方法并吐出两个查询。我不完全确定为什么会这样,我认为第一个查询包含所需的一切...但重要的是实体框架似乎放弃了排序,我无法弄清楚原因。这是由此生成的SQL:
SELECT [t].[Id], [t].[Family], (...some fields omitted...)
FROM (
SELECT [m].[Id], [m].[Family], (...some fields omitted...) ROW_NUMBER() OVER(ORDER BY [m].[Family]) AS [__RowNumber__]
FROM [Members] AS [m]
WHERE (([m].[IsMember] = 1) OR ((
SELECT COUNT(*)
FROM [Members] AS [s]
WHERE [s].[DeceasedDate] IS NULL AND ([m].[Id] = [s].[LivesWithId])
) > 0))
) AS [t]
WHERE ([t].[__RowNumber__] > @__p_0) AND ([t].[__RowNumber__] <= (@__p_0 + @__p_1))
ORDER BY [t].[Id]
SELECT [m0].[Id], [m0].[Family], (...some fields omitted...)
FROM [Members] AS [m0]
WHERE EXISTS (
SELECT 1
FROM (
SELECT [m].[Id], [m].[Family], (...some fields omitted...), ROW_NUMBER() OVER(ORDER BY [m].[Family]) AS [__RowNumber__]
FROM [Members] AS [m]
WHERE ([m].[IsMember] = 1) OR ((
SELECT COUNT(*)
FROM [Members] AS [s]
WHERE [s].[DeceasedDate] IS NULL AND ([m].[Id] = [s].[LivesWithId])
) > 0)
) AS [t]
WHERE (([t].[__RowNumber__] > @__p_0) AND ([t].[__RowNumber__] <= (@__p_0 + @__p_1))) AND ([m0].[LivesWithId] = [t].[Id]))
ORDER BY [m0].[LivesWithId]
这可能并不明显,但实体框架正在做一些破坏指定顺序的有趣业务。它使用skip / take正确拆分组,但是它没有在该组内对结果进行排序,因为它在结尾处以id为单位进行排序。我不完全确定实体框架是否做错了,如果我做的话。我想我的查询可能不是很好,但我很难进行查询,因为它不会为每个结果行执行单独的查询。
编辑:在评论中,它似乎是由EF错误引起的。现在,我可以通过在skip / take
之后输入第二个订单来解决这个问题