Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/278.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 where子句中指定动态字段名?_C#_Linq_Where Clause - Fatal编程技术网

C# 如何在Linq where子句中指定动态字段名?

C# 如何在Linq where子句中指定动态字段名?,c#,linq,where-clause,C#,Linq,Where Clause,如果您创建一个过滤器对象,其中包含Linq的条件,该条件通常位于where子句中,如下所示: var myFilterObject = FilterFactory.GetBlank(); myFilterObject.AddCondition("Salary", "lessThan", "40000"); var myResult = myRepository.GetEmployees(myFilterObject); 在不使用大号格语句的情况下,如何将Linq字段与字段名匹配 re

如果您创建一个过滤器对象,其中包含Linq的条件,该条件通常位于where子句中,如下所示:

 var myFilterObject = FilterFactory.GetBlank();
 myFilterObject.AddCondition("Salary", "lessThan", "40000");

 var myResult = myRepository.GetEmployees(myFilterObject);
在不使用大号格语句的情况下,如何将Linq字段与字段名匹配

 return from e in db.Employee
        where e.Salary < 40000
        select new IList<EmployeeViewModel> { Name= e.name, Salary= e.Salary };
从数据库中的e返回。Employee
其中e.工资<40000
选择新IList{Name=e.Name,Salary=e.Salary};
我假设您需要向指定筛选的存储库发送一个对象,以便只提取您需要的记录。我假设Linq不预编译(除非您创建自定义委托和函数),所以您应该能够动态指定要筛选的字段


如果你能做一些像e[“Salary”]这样的事情,比如某种类型的Expando对象,那就太好了。

我建议你看看Linq to SQL示例。您可以使用它以“纯文本”形式编写条件,例如:

var employees=db.employeen.Where(“工资<40000”)。选择(…);

澄清一下:这些扩展基本上是用通常通过lambdas构造的字符串构建相同的表达式树,因此这与针对数据库编写原始SQL不同。唯一的缺点是不能使用查询理解语法(
from x in y
等)。

可以手动构建表达式,如下所示:

var eParam = Expression.Parameter(typeof(Employee), "e");

var comparison = Expression.Lambda(
    Expression.LessThan(
        Expression.Property(eParam, "Salary"),
        Expression.Constant(40000)),
    eParam);

return from e in db.Employee.Where(comparison)
       select new EmployeeViewModel { Name = e.name, Salary = e.Salary };

我意识到,我参加这次聚会已经很晚了,但是我已经编写了一些代码,我相信这些代码在不使用DynamicLINQ的情况下满足了这一点,我发现DynamicLINQ的支持很差,而且使用起来很不可靠(最多)

//
///在给定泛型实体、propertyName、运算符和值的情况下动态创建表达式的方法。
/// 
/// 
///要为其创建表达式的类。最常见的是使用的实体框架实体
///对于一个DbSet。
/// 
///属性的字符串值。
///枚举类型,包含我们希望支持的所有可能操作。
///值的字符串表示形式。
///值的基础类型
///可用于查询数据集的表达式
私有静态表达式CreateDynamicExpression(字符串propertyName,
运算符op,字符串值,类型valueType)
{
类型=类型(强度);
对象asType=asType(值,值类型);
var p=表达式参数(类型为“x”);
var property=Expression.property(p,propertyName);
方法信息法;
表达q;
开关(op)
{
case Operator.Gt:
q=表达式.GreaterThan(属性,表达式.Constant(asType));
打破
案例操作员。Lt:
q=表达式.LessThan(属性,表达式.Constant(asType));
打破
case运算符.Eq:
q=表达式.Equal(属性,表达式.Constant(asType));
打破
case Operator.Le:
q=Expression.LessThanOrEqual(属性,Expression.Constant(asType));
打破
case Operator.Ge:
q=表达式.GreaterThanOrEqual(属性,表达式.Constant(asType));
打破
case Operator.Ne:
q=Expression.NotEqual(属性,表达式.常量(asType));
打破
案例操作员。包含:
method=typeof(string).GetMethod(“Contains”,new[]{typeof(string)});
q=表达式.Call(属性,方法??抛出新的InvalidOperationException(),
常量(asType,typeof(string));
打破
case Operator.StartsWith:
method=typeof(string).GetMethod(“StartsWith”,new[]{typeof(string)});
q=表达式.Call(属性,方法??抛出新的InvalidOperationException(),
常量(asType,typeof(string));
打破
case Operator.EndsWith:
method=typeof(string).GetMethod(“EndsWith”,new[]{typeof(string)});
q=表达式.Call(属性,方法??抛出新的InvalidOperationException(),
常量(asType,typeof(string));
打破
违约:
抛出新ArgumentOutOfRangeException(nameof(op),op,null);
}
返回表达式λ(q,p);
}
/// 
///将此字符串值提取为传入的对象类型
/// 
///以字符串形式显示的值
///所需类型
///作为指定类型的值
私有静态对象AsType(字符串值,类型)
{
//TODO:此方法需要扩展以包括所有适当的用例
字符串v=值;
if(value.StartsWith(“”)和value.EndsWith(“”)
v=value.Substring(1,value.Length-2);
if(type==typeof(string))
返回v;
if(type==typeof(DateTime))
returndatetime.Parse(v);
if(type==typeof(DateTime?)
returndatetime.Parse(v);
if(type==typeof(int))
返回int.Parse(v);
if(type==typeof(int?)返回int.Parse(v);
抛出新ArgumentException(“尝试对值为“+”值为“+”且类型为”的字段进行筛选”+
类型+“'但是当前不支持此类型”);
}
此代码可用于:

var whereClause = CreateDynamicExpression<MyDatabaseTable>("MyFieldName",
                    Operator.Contains, "some string value",typeof(string));
var results = _db.MyDatabaseTable.Where(whereClause);
var whereClause=CreateDynamicExpression(“MyFieldName”,
运算符。包含“某些字符串值”,typeof(string));
var results=_db.MyDatabaseTable.Where(Where子句);

这是一个非常好的答案。好吧,如果您有一个枚举作为值,那么现在如何使用它?就像用一种很好的方式来添加条件一样。我在尝试实现时遇到了一个编译器错误,请看
    /// <summary>
    ///     A method to create an expression dynamically given a generic entity, and a propertyName, operator and value.
    /// </summary>
    /// <typeparam name="TEntity">
    ///     The class to create the expression for. Most commonly an entity framework entity that is used
    ///     for a DbSet.
    /// </typeparam>
    /// <param name="propertyName">The string value of the property.</param>
    /// <param name="op">An enumeration type with all the possible operations we want to support.</param>
    /// <param name="value">A string representation of the value.</param>
    /// <param name="valueType">The underlying type of the value</param>
    /// <returns>An expression that can be used for querying data sets</returns>
    private static Expression<Func<TEntity, bool>> CreateDynamicExpression<TEntity>(string propertyName,
        Operator op, string value, Type valueType)
    {
        Type type = typeof(TEntity);
        object asType = AsType(value, valueType);
        var p = Expression.Parameter(type, "x");
        var property = Expression.Property(p, propertyName);
        MethodInfo method;
        Expression q;

        switch (op)
        {
            case Operator.Gt:
                q = Expression.GreaterThan(property, Expression.Constant(asType));
                break;
            case Operator.Lt:
                q = Expression.LessThan(property, Expression.Constant(asType));
                break;
            case Operator.Eq:
                q = Expression.Equal(property, Expression.Constant(asType));
                break;
            case Operator.Le:
                q = Expression.LessThanOrEqual(property, Expression.Constant(asType));
                break;
            case Operator.Ge:
                q = Expression.GreaterThanOrEqual(property, Expression.Constant(asType));
                break;
            case Operator.Ne:
                q = Expression.NotEqual(property, Expression.Constant(asType));
                break;
            case Operator.Contains:
                method = typeof(string).GetMethod("Contains", new[] {typeof(string)});
                q = Expression.Call(property, method ?? throw new InvalidOperationException(),
                    Expression.Constant(asType, typeof(string)));
                break;
            case Operator.StartsWith:
                method = typeof(string).GetMethod("StartsWith", new[] {typeof(string)});
                q = Expression.Call(property, method ?? throw new InvalidOperationException(),
                    Expression.Constant(asType, typeof(string)));
                break;
            case Operator.EndsWith:
                method = typeof(string).GetMethod("EndsWith", new[] {typeof(string)});
                q = Expression.Call(property, method ?? throw new InvalidOperationException(),
                    Expression.Constant(asType, typeof(string)));
                break;
            default:
                throw new ArgumentOutOfRangeException(nameof(op), op, null);
        }

        return Expression.Lambda<Func<TEntity, bool>>(q, p);
    }

    /// <summary>
    ///     Extract this string value as the passed in object type
    /// </summary>
    /// <param name="value">The value, as a string</param>
    /// <param name="type">The desired type</param>
    /// <returns>The value, as the specified type</returns>
    private static object AsType(string value, Type type)
    {
        //TODO: This method needs to be expanded to include all appropriate use cases
        string v = value;
        if (value.StartsWith("'") && value.EndsWith("'"))
            v = value.Substring(1, value.Length - 2);

        if (type == typeof(string))
            return v;
        if (type == typeof(DateTime))
            return DateTime.Parse(v);
        if (type == typeof(DateTime?))
            return DateTime.Parse(v);
        if (type == typeof(int))
            return int.Parse(v);
        if (type == typeof(int?)) return int.Parse(v);

        throw new ArgumentException("A filter was attempted for a field with value '" + value + "' and type '" +
                                    type + "' however this type is not currently supported");
    }
var whereClause = CreateDynamicExpression<MyDatabaseTable>("MyFieldName",
                    Operator.Contains, "some string value",typeof(string));
var results = _db.MyDatabaseTable.Where(whereClause);