【问题标题】:EF Core Or Where clause with dynamic具有动态的 EF Core 或 Where 子句
【发布时间】:2021-06-15 10:23:54
【问题描述】:

我无法让动态查询中的 where 子句使用 OR 而不是 AND

结果查询字符串为:

DECLARE @__dateStart_0 datetime2 = '2021-03-15T00:00:00.0000000-03:00';
DECLARE @__dateEnd_1 datetime2 = '2021-03-17T00:00:00.0000000';

SELECT 
    [f].[Id], [f].[DateCreated], [f].[Description], [f].[ExperienceLevel], 
    [f].[PostType], [f].[SocialInteractionsId], [f].[Title], [f].[UserId],
    [q].[ErrorCode], [q].[ErrorName], [q].[RepositoryLink]
FROM
    [ForumPost] AS [f]
INNER JOIN 
    [QuestionsForumPost] AS [q] ON [f].[Id] = [q].[Id]
INNER JOIN 
    [SocialInteractions] AS [s] ON [f].[SocialInteractionsId] = [s].[Id]
WHERE 
    (CONVERT(date, [f].[DateCreated]) >= @__dateStart_0) 
    AND (CONVERT(date, [f].[DateCreated]) <= @__dateEnd_1)
ORDER BY
    [s].[CalculatedInteractions] DESC

预期的查询语句:

WHERE 子句中,应该有一个OR

public async Task<IEnumerable<QuestionsForumPost>> GetQuestionByCriteriaPaged(
    ForumQuestionCriteria forumQuestionCriteria, 
    PaginationFilter paginationFilter)
{
    var query = this._forumContext
        .QuestionsForumPost
        .AsQueryable();

    if (!(forumQuestionCriteria.StartDate is null) && !(forumQuestionCriteria.EndDate is null))
    {
        var dateStart = forumQuestionCriteria.StartDate?.Date;
        var dateEnd = forumQuestionCriteria.EndDate?.Date;

        query = query.Where(qf => qf.DateCreated.Date >= dateStart && qf.DateCreated.Date <= dateEnd);
    }

    if (!String.IsNullOrEmpty(forumQuestionCriteria.Title))
    {
        var wordsArrFromTitle = forumQuestionCriteria.Title.Split(' ');
    
        query = query
            .Where(qf => 
                qf.Title.Split(' ', StringSplitOptions.None)
                .Any(x => wordsArrFromTitle.Contains(x)));
    }

    if (!String.IsNullOrEmpty(forumQuestionCriteria.ErrorCode))
        query = query.Where(qf => qf.ErrorCode.Contains(forumQuestionCriteria.ErrorCode));

    var result = await query
       .Include(qf => qf.SocialInteractions)
       .Skip((paginationFilter.PageNumber - 1) * paginationFilter.PageSize)
       .Take(paginationFilter.PageSize)
       .ToListAsync();

    return result;
}

【问题讨论】:

  • 这个问题需要解决。很多工作。考虑一下,阅读How to Ask,以及如何编写minimal reproducible example
  • 多次调用.Where 导致and 标准。实现Or 需要合并 lambda 表达式树....
  • @TheGeneral 这怎么可能?杰里米·莱克曼(Jeremy Lakeman)明白了,并回答了。谢谢杰里米
  • 仅仅因为有人可以回答并不能使它非常适合该网站,这意味着它将来不太可能帮助任何人。需要修复的格式(并且仍然需要),并且该问题缺少合适的最小示例,并且只是一堆特定时间的文本。考虑阅读有关提问的帮助,或者如果您对为什么这是一篇低质量的帖子有疑问,我建议您将其带到 meta
  • 使用 PredicateBuilder:mitchelsellers.com/blog/article/…

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


【解决方案1】:

我通过安装 linqKit 和使用 predicateBuilder 让它工作了。此外,表达式树不会在运行时将某些 linq 查询转换为 sql,因此需要一个表达式来构造具有所需 linq 查询的新谓词

public async Task<IEnumerable<QuestionsForumPost>> GetQuestionByCriteriaPaged(
            ForumQuestionCriteria forumQuestionCriteria,
            PaginationFilter paginationFilter)
        {
            var criteriaKeyWords = "";

            var query = this._forumContext
                .QuestionsForumPost
                .AsQueryable();

            var dateQuery = PredicateBuilder.New<QuestionsForumPost>();

            var expr = PredicateBuilder.New<QuestionsForumPost>(true);

            if (forumQuestionCriteria.StartDate.HasValue && forumQuestionCriteria.EndDate.HasValue)
            {
                var dateStart = forumQuestionCriteria.StartDate?.Date;
                var dateEnd = forumQuestionCriteria.EndDate?.Date.AddDays(+1);

                dateQuery = dateQuery.Start(qf => (qf.DateCreated >= dateStart && qf.DateCreated <= dateEnd));

                expr.And(dateQuery);
            }

            if (!String.IsNullOrEmpty(forumQuestionCriteria.Title))
            {
                var wordsArrFromTitle = forumQuestionCriteria.Title.ToLower().Split(' ');
                var predicate = ContainsInTitle(wordsArrFromTitle);

                expr = expr.Or(predicate);

                criteriaKeyWords += string.Join(",", wordsArrFromTitle);
            }


            var result = await query
                .Include(qf => qf.SocialInteractions)
                .AsExpandable()
                .Where(expr)
                .Skip((paginationFilter.PageNumber - 1) * paginationFilter.PageSize)
                .Take(paginationFilter.PageSize)
                .ToListAsync();
}


public static Expression<Func<QuestionsForumPost, bool>> ContainsInTitle(
                                                params string[] keywords)
        {
            var predicate = PredicateBuilder.False<QuestionsForumPost>();
            foreach (string keyword in keywords)
            {
                string temp = keyword;
                predicate = predicate.Or(qf => qf.Title.Contains(temp));
            }
            return predicate;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-22
    • 1970-01-01
    • 2018-07-19
    • 2017-05-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多