Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 具有多个/未知条件的动态linq查询_C#_Linq_Dynamic - Fatal编程技术网

C# 具有多个/未知条件的动态linq查询

C# 具有多个/未知条件的动态linq查询,c#,linq,dynamic,C#,Linq,Dynamic,我希望实现一个系统,通过该系统,用户可以使用“构建”条件,然后从数据库返回结果数据。目前,有一个存储过程可以动态生成SQL并执行它。这是我想消除的一个特殊问题 我的问题来自这样一个事实:在我的条件中可以有多个字段,对于每个字段,可能有1个或多个值,具有不同的潜在运算符 比如说, from t in Contacts where t.Email == "email@domain.com" || t.Email.Contains ("mydomain") where t.Field1 == "va

我希望实现一个系统,通过该系统,用户可以使用“构建”条件,然后从数据库返回结果数据。目前,有一个存储过程可以动态生成SQL并执行它。这是我想消除的一个特殊问题

我的问题来自这样一个事实:在我的条件中可以有多个字段,对于每个字段,可能有1个或多个值,具有不同的潜在运算符

比如说,

from t in Contacts 
where t.Email == "email@domain.com" || t.Email.Contains ("mydomain")
where t.Field1 == "valuewewant"
where t.Field2 != "valuewedontwant"
select t
字段、标准和运算符存储在数据库(和
列表
)中,可能是这样的(基于上述内容)

因此,使用我掌握的信息,我希望能够构建一个具有任意数量条件的查询。我已经看到了DynamicLinq和PredicateBuilder之前的链接,但无法将其视为我自己问题的解决方案

如有任何建议,将不胜感激

更新

根据关于动态Linq的建议,我提出了一个非常基本的解决方案,使用一个操作符,包含两个字段和多个条件。正如LinqPad中所编码的,目前有点粗糙,但结果正是我想要的

enum Operator
{
    Equals = 1,
}

class Condition
{
    public string Field { get; set; }
    public Operator Operator { get; set;}
    public string Value { get; set;}
}

void Main()
{
    var conditions = new List<Condition>();

    conditions.Add(new Condition {
        Field = "Email",
        Operator = Operator.Equals,
        Value = "email1@domain.com"
    });

    conditions.Add(new Condition {
        Field = "Email",
        Operator = Operator.Equals,
        Value = "email2@domain.com"
    });

    conditions.Add(new Condition {
        Field = "Field1",
        Operator = Operator.Equals,
        Value = "Chris"
    });

    var statusConditions = "Status = 1";

    var emailConditions = from c in conditions where c.Field == "Email" select c;
    var field1Conditions = from c in conditions where c.Field == "Field1" select c;


    var emailConditionsFormatted = from c in emailConditions select string.Format("Email=\"{0}\"", c.Value);
    var field1ConditionsFormatted = from c in field1Conditions select string.Format("Field1=\"{0}\"", c.Value);

    string[] conditionsArray = emailConditionsFormatted.ToArray();
    var emailConditionsJoined = string.Join("||", conditionsArray);
    Console.WriteLine(String.Format("Formatted Condition For Email: {0}",emailConditionsJoined));

    conditionsArray = field1ConditionsFormatted.ToArray();
    var field1ConditionsJoined = string.Join("||", conditionsArray);
    Console.WriteLine(String.Format("Formatted Condition For Field1: {0}",field1ConditionsJoined));



    IQueryable results = ContactView.Where(statusConditions);

    if (emailConditions != null)
    {
        results = results.Where(emailConditionsJoined);
    }

    if (field1Conditions != null)
    {
        results = results.Where(field1ConditionsJoined);
    }

    results = results.Select("id");

    foreach (int id in results)
    {
        Console.WriteLine(id.ToString());
    }
}
和控制台输出:

Formatted Condition For Email: Email="email1@domain.com"||Email="email2@domain.com"
Formatted Condition For Field1: Field1="Chris"
只需要清理这个,并添加其他运营商,它看起来不错


如果到目前为止有人对此有任何评论,欢迎提供任何意见

我认为动态LINQ将是一种选择。DLINQ允许您将LINQ查询的一部分指定为“字符串”,然后DLINQ将该字符串编译为表达式树,以便传递给基础LINQ提供程序。您的需求也是一样的,即您需要在运行时创建表达式树


我建议您将
FieldCriteria
中的属性
运算符
设置为
Enum
,表示所有必需的操作(等于、小于等)。然后,您需要编写一个函数,该函数获取一个
字段条件列表,并返回一个“表达式”字符串,然后可以将该字符串输入DLINQ以获得表达式树。

LINQ的诀窍是从数据构建
表达式。作为示例,为了说明所示示例:

var param = Expression.Parameter(typeof(MyObject), "t");

var body = Expression.Or(
            Expression.Equal(Expression.PropertyOrField(param, "Email"), Expression.Constant("email@domain.com")),
            Expression.Call(Expression.PropertyOrField(param, "Email"), "Contains", null, Expression.Constant("mydomain"))
        );

body = Expression.AndAlso(body, Expression.Equal(Expression.PropertyOrField(param, "Field1"), Expression.Constant("valuewewant")));
body = Expression.AndAlso(body, Expression.NotEqual(Expression.PropertyOrField(param, "Field2"), Expression.Constant("valuewedontwant")));

var lambda = Expression.Lambda<Func<MyObject, bool>>(body, param);

var data = source.Where(lambda);
var param=Expression.Parameter(typeof(MyObject),“t”);
变量体=表达式。或(
Expression.Equal(Expression.PropertyOrField(参数,“Email”)、Expression.Constant(“email@domain.com")),
Expression.Call(Expression.PropertyOrField(param,“Email”),“Contains”,null,Expression.Constant(“mydomain”))
);
body=Expression.AndAlso(body,Expression.Equal(Expression.PropertyOrField(param,“Field1”)、Expression.Constant(valuewewant));
body=Expression.AndAlso(body,Expression.NotEqual(Expression.PropertyOrField(param,“Field2”)、Expression.Constant(valuewedontwand));
var lambda=表达式.lambda(body,param);
var数据=来源,其中(λ);

特别是,请注意如何使用
组合各种操作(与多个
Where
相同,但更简单)。

这可以通过Linq完成,在Linq中,您可以向查询对象附加额外的运算符。这里有一个例子

query = db.Contacts.Where( ... );
 query = query.Where( ... );
 query = query.Where( ... );

这是一个更简单、更简短的解决方案。

LINQ to的整个思想是将静态C#编译时表达式转换为某种字符串,发送到底层数据库执行。您建议使用字符串转换为linq表达式,然后再转换为字符串,这似乎有点多余:)关于SQL的“静态”表达式,您是正确的,但在这个问题上,用户在编译时不知道表达式,因此需要在运行时生成表达式。DLINQ是从“字符串”执行的一种方法,另一种方法是使用表达式API在运行时创建所需的表达式。上面的代码是否不要求您知道字段/条件/运算符。在我的场景中。在编译时,没有一个是已知的,在这方面它需要是完全动态的。请原谅,我弄错了,因为Lambda函数有点超出了我目前的知识范围。@Chris没有,但您必须编写一些代码来生成表达式如何在inside where子句中使用?这是for AND logic,但是OR logic呢?
Formatted Condition For Email: Email="email1@domain.com"||Email="email2@domain.com"
Formatted Condition For Field1: Field1="Chris"
var param = Expression.Parameter(typeof(MyObject), "t");

var body = Expression.Or(
            Expression.Equal(Expression.PropertyOrField(param, "Email"), Expression.Constant("email@domain.com")),
            Expression.Call(Expression.PropertyOrField(param, "Email"), "Contains", null, Expression.Constant("mydomain"))
        );

body = Expression.AndAlso(body, Expression.Equal(Expression.PropertyOrField(param, "Field1"), Expression.Constant("valuewewant")));
body = Expression.AndAlso(body, Expression.NotEqual(Expression.PropertyOrField(param, "Field2"), Expression.Constant("valuewedontwant")));

var lambda = Expression.Lambda<Func<MyObject, bool>>(body, param);

var data = source.Where(lambda);
query = db.Contacts.Where( ... );
 query = query.Where( ... );
 query = query.Where( ... );