动态LINQ - 是否有.NET 4版本?

时间:2011-03-02 03:43:32

标签: c# linq dynamic-linq linq-expressions

我正在寻找一些搜索例程使用LINQ,并希望有一些动态where子句。因此,例如,如果用户想要按城市搜索或按州搜索,我会有一个动态LINQ Where<>调用而不是创建两个强类型LINQ表达式,然后根据用户想要搜索的方式使用适当的LINQ表达式。

所以我想这样做:

String criteria="p.City='Pittsburgh'";  //or "p.State='PA'"
personData.Where(criteria)

而不是

personData.Where(p => p.City=="Pittsburgh");

personData.Where(p => p.State=="PA");

Scott Guthrie在Visual Studio 2008示例中谈到了动态LINQ,我遇到了blog post。这似乎做我想要的,但我的问题是:

  1. 此示例库是否受Microsoft支持?
  2. Scott Guthrie的文章是关于VS2008(.NET 3.5)的。 .NET 4有更好的选择吗?也许用.NET 4发布的东西可以完成同样的事情(或者非常接近的东西)?
  3. 提前致谢!

4 个答案:

答案 0 :(得分:9)

您可能需要查看PredicateBuilder

答案 1 :(得分:6)

这个功能真的很棒。 ADO.net数据表中存在类似的功能。这对 LinqToSql 也很有帮助。当然你会失去强类型检查,但这就是重点,你想要动态搜索。如果你正确处理异常我真的认为它是一个值得拥有的功能。

您可以考虑向Microsoft Connect添加功能请求。图书馆已经存在,也许他们会考虑增加对它的官方支持。如果您确实发出了功能请求,请确保在此处发布链接,以便我们对其进行投票。 Microsoft Connect具有类似于stackoverflow的投票系统。我自己提交了一些LinqtoSql TableUpdateVB.net Readonly Interfaces like C#

我记得在使用这个库时遇到了一些麻烦。我认为它与静态方法有关。

我发现开发我需要的表达式会更好。 Ilya Builuk的article演示了自定义表达式。关于Ilya框架的好处是它在执行像jqGrid的排序操作时删除了很多样板代码。

在了解表达式的基本概念时,我发现它非常有用。

这段代码的好处在于它允许你使用点运算符来获取getter。 Person.Age或者如果你想违反Demeter,你甚至可以做多个吸气剂。

可以改进代码。我相信我添加了StartsWith并且只允许它用于字符串操作以及其他一些搜索操作。无论它值得一看,它帮助我理解了linq表达式。

public static IQueryable<T> Where<T>(this IQueryable<T> query, string column, object value, WhereOperation operation)
{
    if (string.IsNullOrEmpty(column))
        return query;

    ParameterExpression parameter = Expression.Parameter(query.ElementType, "p");

    MemberExpression memberAccess = null;
    foreach (var property in column.Split('.'))
        memberAccess = MemberExpression.Property
           (memberAccess ?? (parameter as Expression), property);

    //change param value type
    //necessary to getting bool from string
    ConstantExpression filter = Expression.Constant
        (
            Convert.ChangeType(value, memberAccess.Type)
        );

    //switch operation
    Expression condition = null;
    LambdaExpression lambda = null;
    switch (operation)
    {
        //equal ==
        case WhereOperation.Equal:
            condition = Expression.Equal(memberAccess, filter);
            lambda = Expression.Lambda(condition, parameter);
            break;
        //not equal !=
        case WhereOperation.NotEqual:
            condition = Expression.NotEqual(memberAccess, filter);
            lambda = Expression.Lambda(condition, parameter);
            break;
        //string.Contains()
        case WhereOperation.Contains:
            condition = Expression.Call(memberAccess,
                typeof(string).GetMethod("Contains"),
                Expression.Constant(value));
            lambda = Expression.Lambda(condition, parameter);
            break;
    }


    MethodCallExpression result = Expression.Call(
           typeof(Queryable), "Where",
           new[] { query.ElementType },
           query.Expression,
           lambda);

    return query.Provider.CreateQuery<T>(result);
}

WhereOperation枚举器:

public enum WhereOperation { Equal, NotEqual, Contains }

答案 2 :(得分:4)

它现在应该可用。我可以通过NuGet下载它:http://www.nuget.org/packages/System.Linq.Dynamic/

答案 3 :(得分:1)

我认为它不受微软“支持” - 它似乎是在公共许可下发布的,部分原因是:

  

(E)该软件按“原样”许可。   您自行承担使用的风险。该   贡献者没有表达   保证,担保或条件。   您可能有其他消费者   您当地法律规定的权利   此许可证无法更改。到了   在您当地允许的范围内   法律,贡献者排除了   对适销性的暗示保证,   适合特定目的和   非侵害。

关于第二个问题,我认为没有.NET 4版本。 3.5应该可以在4.0项目中正常工作,我认为没有太多可以添加的内容。据我所知,这是一个漂亮的小型库,用于执行偶尔的,基于字符串的一次性linq查询。也许您出于某种原因手动排序网格,并且需要根据表示相关属性的字符串修改集合排序顺序。瞧。我怀疑你会为此添加很多功能而付出很多努力。