代码之家  ›  专栏  ›  技术社区  ›  Benehmb

C#Linq All in Where条件

  •  0
  • Benehmb  · 技术社区  · 2 年前

    我有以下LinqExpression:

    var results = _localDatabase.Table<ArticleData>().Where(article =>
        article.ArticleName!.ToLower().Contains(searchQuery.ToLower());
    

    它的缺点是,被搜索的文本必须是文章名称的一部分。但有时,用户只输入部分单词(文章名称为 Spider-Man: Across the Spider-Verse 和用户搜索 man 和 verse ). 因此,我将搜索查询分为几个部分:

    string[] splitQuerry = searchQuery.Split(' ');
    

    并尝试搜索各个部分:

    var results = _localDatabase.Table<ArticleData>().Where(article =>
        splitQuerry.All<string>(querryPart => article.ArticleName!.Contains(querryPart)));
    

    理论上,这听起来很棒,但在实践中,我得到了 Cannot compile: Lambda 例外

    太长,读不下去了

    我需要一种方法来包装这样的东西——所有方法,或者类似的东西 this 到Linq表达式中。

    编辑

    我有一个SQLite数据库。具有 _localDatabase.Table<ArticleData>() ,我得到一个可查询的对象。

    2 回复  |  直到 2 年前
        1
  •  0
  •   SomeBody    2 年前

    您可以使用个人 Where splitQuerry中每个项的子句:

    var query = _localDatabase.Table<ArticleData>().AsQueryable();
    foreach(var item in splitQuerry )
    {
        query = query.Where(article => article.ArticleName!.ToLower().Contains(item.ToLower()));
    }
    query = query.Skip(startIndex ?? 0).Take(requestedNumberOfItems ?? 5);
    var result = query.ToList();
    
        2
  •  0
  •   jakub podhaisky    2 年前

    我已经创建了一个控制台应用程序,它可以做你想要做的事情。我认为你可以使用这个例子来获得你需要做的事情,请检查评论部分,该部分返回任何与查询的一部分匹配的内容

    using System.Linq.Expressions;
    
    namespace DynamicSearchExample
    {
        class Program
        {
            static async Task Main(string[] args)
            {
                var articles = new List<ArticleData>
                {
                    new ArticleData { ArticleName = "Spider-Man: Across the Spider-Verse" },
                    new ArticleData { ArticleName = "Iron Man: The Rise of Iron" },
                    new ArticleData { ArticleName = "The Amazing Spider-Man" }
                };
    
                string searchQuery = "amaZing MaN";
    
                var searchResults = await SearchArticles(articles, searchQuery, startIndex: null, requestedNumberOfItems: null);
    
                Console.WriteLine("Search results:");
                foreach (var result in searchResults)
                {
                    Console.WriteLine(result.ArticleName);
                }
            }
    
            //public static Expression<Func<ArticleData, bool>> BuildSearchExpression(string[] queryParts)
            //{
            //    var parameter = Expression.Parameter(typeof(ArticleData), "article");
    
            //    // Create expressions for each query part
            //    var containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });
            //    var property = Expression.Property(parameter, "ArticleName");
            //    var containsExpressions = queryParts.Select(queryPart =>
            //    {
            //        var value = Expression.Constant(queryPart.ToLower(), typeof(string));
            //        var propertyToLower = Expression.Call(property, typeof(string).GetMethod("ToLower", Type.EmptyTypes));
            //        var containsCall = Expression.Call(propertyToLower, containsMethod, value);
            //        return Expression.Convert(containsCall, typeof(bool));
            //    });
    
            //    // Combine expressions using OR operation
            //    Expression body = null;
            //    foreach (var expression in containsExpressions)
            //    {
            //        if (body == null)
            //        {
            //            body = expression;
            //        }
            //        else
            //        {
            //            body = Expression.OrElse(body, expression);
            //        }
            //    }
    
            //    return Expression.Lambda<Func<ArticleData, bool>>(body, parameter);
            //}
            public static Expression<Func<ArticleData, bool>> BuildSearchExpression(string[] queryParts)
            {
                var parameter = Expression.Parameter(typeof(ArticleData), "article");
    
                // Create expressions for each query part
                var containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });
                var property = Expression.Property(parameter, "ArticleName");
                var propertyToLower = Expression.Call(property, typeof(string).GetMethod("ToLower", Type.EmptyTypes));
    
                // Combine expressions using AND operation
                Expression body = null;
                foreach (var queryPart in queryParts)
                {
                    var value = Expression.Constant(queryPart.ToLower(), typeof(string));
                    var containsCall = Expression.Call(propertyToLower, containsMethod, value);
                    var partExpression = Expression.Convert(containsCall, typeof(bool));
    
                    if (body == null)
                    {
                        body = partExpression;
                    }
                    else
                    {
                        body = Expression.AndAlso(body, partExpression);
                    }
                }
    
                return Expression.Lambda<Func<ArticleData, bool>>(body, parameter);
            }
    
    
    
    
    
    
            // Sample ArticleData class
            public class ArticleData
            {
                public string ArticleName { get; set; }
            }
    
            // Sample method to simulate database search
            public static async Task<List<ArticleData>> SearchArticles(List<ArticleData> articles, string searchQuery, int? startIndex, int? requestedNumberOfItems)
            {
                // Split the search query into individual parts
                string[] splitQuery = searchQuery.Split(' ');
    
                // Build the dynamic LINQ expression
                var searchExpression = BuildSearchExpression(splitQuery);
    
                // Execute the query asynchronously
                var task = Task.Run(() => articles
                    .AsQueryable()
                    .Where(searchExpression)
                    .Skip(startIndex ?? 0)
                    .Take(requestedNumberOfItems ?? 5)
                    .ToList());
    
                return await task;
            }
        }
    }