C#-MongoDB:在Where子句中使用OR操作符的列表。

问题描述 投票:0回答:2

我有一个类别列表,我正在创建一个动态查询。

var Categories = GetCategories(); //list of string
query = query.Where(x => x.CategoryID == ?????);

现在,我怎样才能使类别列表在where子句中的每个类别都有一个OR操作符?

例如,让我们假设Categories列表有两个类别,所以它将像。

query = query.Where(x => x.CategoryID == Categories[0] | x.CategoryID == Categories[1]);

但这必须是动态的

c# mongodb linq lambda dynamicquery
2个回答
1
投票

你可以这样做

query.Where(x => Categories.Contains(x.CategoryID))

0
投票

我最后这样做了,而且成功了。

var subChildCategories = GetChildCategories(Convert.ToInt32(getProductsDomainModel.CategoryID));
var parameter = Expression.Parameter(typeof(FullProductDomainModel));
BinaryExpression binaryExpression = null;

foreach (var category in subChildCategories)
{
    var prop = Expression.Property(parameter, "CategoryID");
    var value = Expression.Constant(category.ToString());
    var newBinary = Expression.MakeBinary(ExpressionType.Equal, prop, value);

    binaryExpression =
        binaryExpression == null
        ? newBinary
        : Expression.MakeBinary(ExpressionType.Or, binaryExpression, newBinary);
}

var cookedExpression = Expression.Lambda<Func<FullProductDomainModel, bool>>(binaryExpression, parameter).Compile();

query = query.Where(cookedExpression).AsQueryable();

0
投票

我希望这个解决方案能帮助我,以防我原来的答案建议使用表达式树没有用。

这段代码

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp39
{
    class Program
    {
        public struct CategoryEntry {
            public int Id { get; set; }
            public string Description { get; set; }
        }

        static void Main(string[] args)
        {
            var categories = new List<CategoryEntry>();
            categories.Add(new CategoryEntry() { Id = 1, Description = "1-First"});
            categories.Add(new CategoryEntry() { Id = 1, Description = "1-Second" });
            categories.Add(new CategoryEntry() { Id = 2, Description = "2-First" });
            categories.Add(new CategoryEntry() { Id = 3, Description = "3-First" });

            var categoryIDs = new HashSet<int>();
            categoryIDs.Add(1);
            categoryIDs.Add(2);

            Console.WriteLine("The sought Ids \n");
            foreach (var categoryId in categoryIDs) {
                Console.WriteLine(categoryId);
            }
            Console.WriteLine("\n");

            // returns a collection of collections, one collection per queried category id
            var result = categoryIDs.Select(id => categories.FindAll(c => c.Id == id));
            Console.WriteLine("The result from the variable result \n");
            foreach (var collection in result)
            {
                collection.ForEach(entry => Console.WriteLine(entry.Description));
            }

            Console.WriteLine("\n");
            // returns a single collection with all found categories for all queried categories ids 
            var flatResult = categoryIDs.SelectMany(id => categories.FindAll(c => c.Id == id));
            Console.WriteLine("The result from the variable flatResult \n");
            foreach (var entry in flatResult)
            {
                Console.WriteLine(entry.Description);
            }

            Console.ReadLine();
        }
    }
}

输出

寻找的Ids

12

变量 result 的结果

1-第一1-第二2-第一

变量flatResult的结果

1-第一1-第二2-第一


-1
投票

看来你需要使用 表达式树(C#)

表达式树以树状数据结构表示代码,其中每个节点是一个表达式,例如,一个方法调用或二进制操作,如x < y。

您可以编译和运行由表达式树表示的代码。这样就可以动态修改可执行代码,在各种数据库中执行LINQ查询,以及创建动态查询。 有关LINQ中表达式树的更多信息,请参见 如何使用表达式树构建动态查询(C#).

下面是一个非常简单的例子,可以从这个例子入手。

下面的代码示例演示了如何编译表达式树并运行生成的代码。

    // Creating an expression tree.  
    Expression<Func<int, bool>> expr = num => num < 5;  

    // Compiling the expression tree into a delegate.  
    Func<int, bool> result = expr.Compile();  

    // Invoking the delegate and writing the result to the console.  
    Console.WriteLine(result(4));  

    // Prints True.  

    // You can also use simplified syntax  
    // to compile and run an expression tree.  
    // The following line can replace two previous statements.  
    Console.WriteLine(expr.Compile()(4));  

    // Also prints True.

下面是一个如何使用表达式树来构建动态查询的例子。如何使用表达式树构建动态查询(C#):

下面的例子展示了如何使用表达式树来构建一个针对IQueryable数据源的查询,然后执行它。这段代码建立了一个表达式树来表示下面的查询。

   companies.Where(company => (company.ToLower() == "coho winery" ||
       company.Length > 16))
          .OrderBy(company => company)

System.Linq.Expressions命名空间中的工厂方法被用来创建表达式树,这些表达式代表了构成整个查询的表达式。表示对标准查询操作符方法的调用的表达式是指这些方法的Queryable实现。最后的表达式树被传递给IQueryable数据源提供者的CreateQuery(Expression)实现,以创建IQueryable类型的可执行查询。通过枚举该查询变量来获得结果。

// Add a using directive for System.Linq.Expressions.  

string[] companies = { "Consolidated Messenger", "Alpine Ski House", "Southridge Video", "City Power & Light",  
                   "Coho Winery", "Wide World Importers", "Graphic Design Institute", "Adventure Works",  
                   "Humongous Insurance", "Woodgrove Bank", "Margie's Travel", "Northwind Traders",  
                   "Blue Yonder Airlines", "Trey Research", "The Phone Company",  
                   "Wingtip Toys", "Lucerne Publishing", "Fourth Coffee" };  

// The IQueryable data to query.  
IQueryable<String> queryableData = companies.AsQueryable<string>();  

// Compose the expression tree that represents the parameter to the predicate.  
ParameterExpression pe = Expression.Parameter(typeof(string), "company");  

// ***** Where(company => (company.ToLower() == "coho winery" || company.Length > 16)) *****  
// Create an expression tree that represents the expression 'company.ToLower() == "coho winery"'.  
Expression left = Expression.Call(pe, typeof(string).GetMethod("ToLower", System.Type.EmptyTypes));  
Expression right = Expression.Constant("coho winery");  
Expression e1 = Expression.Equal(left, right);  

// Create an expression tree that represents the expression 'company.Length > 16'.  
left = Expression.Property(pe, typeof(string).GetProperty("Length"));  
right = Expression.Constant(16, typeof(int));  
Expression e2 = Expression.GreaterThan(left, right);  

// Combine the expression trees to create an expression tree that represents the  
// expression '(company.ToLower() == "coho winery" || company.Length > 16)'.  
Expression predicateBody = Expression.OrElse(e1, e2);  

// Create an expression tree that represents the expression  
// 'queryableData.Where(company => (company.ToLower() == "coho winery" || company.Length > 16))'  
MethodCallExpression whereCallExpression = Expression.Call(  
    typeof(Queryable),  
    "Where",  
    new Type[] { queryableData.ElementType },  
    queryableData.Expression,  
    Expression.Lambda<Func<string, bool>>(predicateBody, new ParameterExpression[] { pe }));  
// ***** End Where *****  

// ***** OrderBy(company => company) *****  
// Create an expression tree that represents the expression  
// 'whereCallExpression.OrderBy(company => company)'  
MethodCallExpression orderByCallExpression = Expression.Call(  
    typeof(Queryable),  
    "OrderBy",  
    new Type[] { queryableData.ElementType, queryableData.ElementType },  
    whereCallExpression,  
    Expression.Lambda<Func<string, string>>(pe, new ParameterExpression[] { pe }));  
// ***** End OrderBy *****  

// Create an executable query from the expression tree.  
IQueryable<string> results = queryableData.Provider.CreateQuery<string>(orderByCallExpression);  

// Enumerate the results.  
foreach (string company in results)  
    Console.WriteLine(company);  

/*  This code produces the following output:  

    Blue Yonder Airlines  
    City Power & Light  
    Coho Winery  
    Consolidated Messenger  
    Graphic Design Institute  
    Humongous Insurance  
    Lucerne Publishing  
    Northwind Traders  
    The Phone Company  
    Wide World Importers  
*/
© www.soinside.com 2019 - 2024. All rights reserved.