31

我希望将 LINQ 用于一些搜索例程,并希望有一些动态的 where 子句。因此,例如,如果用户想要按城市搜索或按州搜索,我将使用动态 LINQ Where<> 调用,而不是创建两个强类型 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。这似乎符合我的要求,但我的问题是:

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

提前致谢!

4

4 回答 4

10

您可能想看看PredicateBuilder

于 2011-03-02T04:04:18.743 回答
6

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

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

我记得这个图书馆遇到了一些麻烦。我认为这与静态方法有关。

我发现开发我需要的表达方式会更好。Ilya Builuk 的这篇文章演示了自定义表达式。Ilya 框架的优点在于它在执行 jqGrid 排序等操作时删除了许多样板代码。

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

这段代码的好处是它允许您对 getter 使用点运算符。Person.Age或者如果你想违反 Demeter,你甚至可以做多个 getter。

代码可以改进。我相信我添加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 }
于 2011-03-03T00:45:36.013 回答
5

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

于 2014-01-17T12:55:22.710 回答
1

我不认为微软“支持”它——它似乎是根据公共许可证发布的,其中部分内容是:

(E) 软件按“原样”获得许可。您自行承担使用的风险。贡献者不提供任何明示的保证、保证或条件。根据当地法律,您可能拥有本许可无法更改的其他消费者权利。在您当地法律允许的范围内,贡献者排除了对适销性、特定用途适用性和不侵权的默示保证。

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

于 2011-03-02T03:49:26.310 回答