2

我看过一些旧帖子,但无法弄清楚如何实现这一点,请举个例子。

我正在对 DataTable 运行查询以对所有列进行分组。数字列只会被称为运行时,因此我需要动态构建查询。

var newGroup = from row in dataTable.AsEnumerable() 
group row by new { ID = row.Field<string>("column1"), group1 = row.Field<string>("column2") };

我需要为n number of columns.

请解释如何通过遍历列列表并构建 Lambda 表达式来构建 ParameterExpression。

4

3 回答 3

0

简而言之:有不同的方法可以实现这一目标。困难的方法是通过使用表达式来构建 Func 和 Predicates 的组合。更简单的方法是使用库 -LINQ Dynamic Query Library如下所述:

解决方案#1:这是一个很好的起点——在 C# 运行时构建 LINQ 查询

解决方案#2:您应该也可以通过使用来做到这一点Linq Dynamic Query,因为它为此目的而构建 -动态 LINQ(第 1 部分:使用 LINQ 动态查询库)

于 2013-01-16T04:48:03.813 回答
0

我多次看到这个问题,所以我决定创建一个博客,而不是从 C# 操作数据。我通过使用动态 SQL 完成了 SQL 数据库级别的繁重工作。

这是链接。希望这可以帮助。

于 2013-01-16T06:26:55.213 回答
0

我有一种情况,我需要为查询的左侧和右侧动态生成 LINQ 查询。换句话说,Where("some property == some value")。我从 LINQPad 的人那里玩过 PredicateBuilder,并尝试了其他一些东西,但最终 LINQ 动态查询库 (System.Linq.Dynamic) 使这项任务变得非常简单。

在不详细介绍所有细节的情况下,我所拥有的是一种方法,它采用参数来过滤和排序 MVC 页面上 jqGrid 上的项目。一个名为 QueryOptions 的对象包含各种查询设置。Data.ImportDataSearchView 是绑定到后端数据库视图的实体框架实体。

过滤器表达式是通过调用建立的:

        options.FilterExpression += filterList.BuildFilterExpression<Data.ImportDataSearchView>();

BuildFilterExpression 的一部分如下:

    public string BuildFilterExpression<T>()
    {
        var type = typeof(T);
        var exp = string.Empty;

        foreach (Filter filter in this)
        {
            var typeName = filter.DataType.ToLower();

            // Skip if no values
            if (!filter.Values.Any())
                continue;

            switch (typeName)
            {
                case "string":
                    // html decode string and escape single quotes
                    var stringVal = System.Web.HttpUtility.HtmlDecode(filter.Values[0]);
                    stringVal = stringVal.Replace("'", "''");

                    if (filter.Operator == Enums.FilterOperator.CONTAINS)
                        exp += string.Format("{0}.Trim().ToLower().Contains(\"{1}\")", filter.Attribute, stringVal.Trim().ToLower());

                    else if (filter.Operator == Enums.FilterOperator.DOES_NOT_EQUAL)
                        exp += string.Format("!{0}.ToLower().Equals(\"{1}\")", filter.Attribute, stringVal.ToLower());

                    else if (filter.Operator == Enums.FilterOperator.DOES_NOT_CONTAIN)
                        exp += string.Format("!{0}.Trim().ToLower().Contains(\"{1}\")", filter.Attribute, stringVal.Trim().ToLower());

                    else if (filter.Operator == Enums.FilterOperator.ENDS_WITH)
                        exp += string.Format("{0}.Trim().ToLower().EndsWith(\"{1}\")", filter.Attribute, stringVal.Trim().ToLower());

                    else if (filter.Operator == Enums.FilterOperator.EQUALS)
                        exp += string.Format("{0}.ToLower().Equals(\"{1}\")", filter.Attribute, stringVal.ToLower());

                    else if (filter.Operator == Enums.FilterOperator.STARTS_WITH)
                        exp += string.Format("{0}.Trim().ToLower().StartsWith(\"{1}\")", filter.Attribute, stringVal.Trim().ToLower());

                    break;

                //case "select": -- for dropdowns
                //case "datetime": -- for dates, etc. etc.

            // add spaces around expression
            exp = string.Format(" {0} ", exp);

            // add and/or to expression
            if (this.IndexOf(filter) != this.Count() - 1)
                exp += string.Format(" {0} ", ExpressionType.ToLower() == "and" ? "&&" : "||");
        }

        return exp;
    }

然后在构建表达式字符串后,按如下方式检索数据:

        options.OrderBy = string.IsNullOrEmpty(sortIndex) ? "TrackingId asc" : string.Format(" {0} {1} ", sortIndex, sortOrder);

        var db = new Data.BmpDB();
        var list = string.IsNullOrEmpty(options.FilterExpression)
            ? db.ImportDataSearchViews.OrderBy(options.OrderBy).ToList()
            : db.ImportDataSearchViews.Where(options.FilterExpression).OrderBy(options.OrderBy).ToList();

下面的 options.FilterExpression 字符串是三个搜索条件字段的示例,这些字段由 BuildFilterExpression 方法拼凑成一个漂亮、简单的 LINQ where 子句谓词字符串:

"BmpName.Trim().ToLower().Contains(\"crops\") && DataProviderId.ToLower().Equals(\"123\") && StatusId == 1"

于 2016-06-09T19:07:03.313 回答