使用Skip / Take with Subquery

时间:2017-02-28 20:43:26

标签: c# asp.net-core entity-framework-core

我使用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

之后输入第二个订单来解决这个问题

0 个答案:

没有答案