Efcore 2.2- where 子句在选择后运行并且 returns 错误结果

Efcore 2.2- where clause runs after selection and returns false results

我有这个简单的查询:

Expression<Func<Tips, bool>> lastTipsPredicate = x => x.Status == (int)EnumGringo.LU_Status.active;

IQueryable<Tips> lastQueryBase(DbSet<Tips> t) => t.OrderByDescending(x => x.CreateDate).Take(6);
IEnumerable<Tips> latestTips = await base.GetAllByCondition(lastTipsPredicate, lastQueryBase);

这是我的基本存储库:

public virtual async Task<IEnumerable<TEntity>> GetAllByCondition(Expression<Func<TEntity, bool>> predicate, Func<DbSet<TEntity>, IQueryable<TEntity>> baseQuery = null)
        {
            IQueryable<TEntity> q = context.Set<TEntity>();

            if (baseQuery != null)
            {
                q = baseQuery(context.Set<TEntity>());
            }

            return await q.Where(predicate).ToListAsync();
        }

这会生成这个 sql 查询(来自探查器):

exec sp_executesql N'SELECT [t].[ID], [t].[CreateDate], [t].[Description], [t].[InsertedByGringo], [t].[IsRecommended], [t].[IsSubscribe], [t].[LanguageType], [t].[SeoId], [t].[Slug], [t].[Status], [t].[Title], [t].[UserID], [t].[ViewCount]
FROM (
    SELECT TOP(@__p_0) [x].[ID], [x].[CreateDate], [x].[Description], [x].[InsertedByGringo], [x].[IsRecommended], [x].[IsSubscribe], [x].[LanguageType], [x].[SeoId], [x].[Slug], [x].[Status], [x].[Title], [x].[UserID], [x].[ViewCount]
    FROM [Tips] AS [x]
    ORDER BY [x].[CreateDate] DESC
) AS [t]
WHERE [t].[Status] = 1',N'@__p_0 int',@__p_0=6

其中 returns 只有 5 条记录,而不是我预期的 6 条,1 条记录被过滤掉,因为它有状态!=1.

虽然此查询是正确的并且 returns 最后 6 条记录:

SELECT top 6 [t].[ID], [t].[CreateDate], [t].[Description], [t].[InsertedByGringo], [t].[IsRecommended], [t].[IsSubscribe], [t].[LanguageType], [t].[SeoId], [t].[Slug], [t].[Status], [t].[Title], [t].[UserID], [t].[ViewCount]
FROM Tips as [t]
WHERE [t].[Status] = 1
ORDER BY [t].CreateDate DESC

如何生成第二个查询而不是第一个?

Efcore 2.2- where clause runs after selection and returns false results

这既不是 EF Core 也不是 LINQ 问题,而是您的存储库方法构建 LINQ 查询的方式。

如果您想先应用过滤 (Where),然后选择性地应用其余的,那么您应该将 baseQuery 函数输入类型从 DbSet<TEntity> 更改为 IQueryable<TEntity> ,实现如下:

public virtual async Task<IEnumerable<TEntity>> GetAllByCondition(
    Expression<Func<TEntity, bool>> predicate,
    Func<IQueryable<TEntity>, IQueryable<TEntity>> baseQuery = null)
{
    var q = context.Set<TEntity>()
        .Where(predicate); // <-- (1)

    if (baseQuery != null)
        q = baseQuery(q); // <-- (2)

    return await q.ToListAsync();
}