【问题标题】:Dynamic Linq on DataTable error: no Field or Property in DataRow, c#DataTable 上的动态 Linq 错误:DataRow 中没有字段或属性,c#
【发布时间】:2016-03-07 07:26:10
【问题描述】:

我在 DataTable 上使用 Linq 时遇到了一些错误,我不知道如何解决它。我不得不承认我对 Linq 很陌生,我搜索了论坛和互联网,但无法弄清楚。希望你能帮忙。

我有一个名为 campaign 的 DataTable,它包含三列:ID (int)、Product (string)、Channel (string)。 DataTable 已经填充了数据。我正在尝试选择满足最终用户选择的条件的活动记录子集。例如,仅当产品是“EWH”或“HEC”时,用户才想列出。选择标准由最终用户动态确定。

我有以下 C# 代码:

private void btnClick()
{
IEnumerable<DataRow> query =
                from zz in campaign.AsEnumerable()
                orderby zz.Field<string>("ID")
                select zz;
string whereClause = "zz.Field<string>(\"Product\") in ('EWH','HEC')";
query = query.Where(whereClause);
DataTable sublist = query.CopyToDataTable<DataRow>();
}

但它给我一个在线错误:query = query.Where(whereClause),说

“DataRow”类型中不存在属性或字段“zz”。

如果我改为: string whereClause = "Product in ('EWH','HEC')"; 它会说:

“DataRow”类型中不存在“产品”属性或字段

谁能帮我解决这个问题?我觉得这可能是一个非常简单的语法更改,但我现在不知道。

【问题讨论】:

    标签: linq datatable


    【解决方案1】:

    首先,这一行有错误

    orderby zz.Field<string>("ID")
    

    因为正如您所说,您的 ID 列的类型为 int

    其次,您需要学习 LINQ 查询语法。忘记字符串,就像你在查询中使用fromorderbyselect 一样,你也可以使用where 和许多其他运算符。此外,您还需要学习与 SQL 类似的事物的等效 LINQ 构造,例如 IN (...) 映射到 Enumerable.Contains 等。

    说了这么多,这是您的问题

    var productFilter = new[] { "EWH", "HEC" };
    var query =
        from zz in campaign.AsEnumerable()
        where productFilter.Contains(zz.Field<string>("Product"))
        orderby zz.Field<int>("ID")
        select zz;
    

    更新根据您的评论,如果您想让这个动态化,那么您需要切换到 lambda 语法。多个and 条件可以通过像这样链接多个Where 子句来组成

    List<string> productFilter = ...; // coming from outside
    List<string> channelFilter = ...; // coming from outside
    var query = campaign.AsEnumerable();
    // Apply filters if needed
    if (productFilter != null && productFilter.Count > 0)
        query = query.Where(zz => productFilter.Contains(zz.Field<string>("Product")));
    if (channelFilter != null && channelFilter.Count > 0)
        query = query.Where(zz => channelFilter.Contains(zz.Field<string>("Channel")));
    // Once finished with filtering, do the ordering
    query = query.OrderBy(zz => zz.Field<int>("ID"));
    

    【讨论】:

    • 伊万,这很有帮助。正如您所指出的,ID 应该是 int。在您的代码中,您使用 productFilter 仅保留所需的条目。它按预期工作。但是,另一个障碍是用户可能根本不应用任何 productFilter,或者他们在 Channel 或多个过滤器的任何组合上具有过滤器(我在原始帖子中仅列出 Product 和 Channel 作为示例)。如何动态设置 WHERE 子句?
    • 这继续我的评论,因为有长度限制。我可以构建一个长字符串来动态连接过滤器,例如:'string whereClause="productFilter.Contains(zz.Field("Product")) 和 channelFilter.Contains(zz.Field("Channel") )',但我不能把这个变量放在 WHERE 后面,因为它需要一些指定的条件而不是字符串变量,尽管字符串的表达式是条件。不确定我是否把问题说清楚了。非常感谢你的帮助。
    • @sguo 我用动态过滤的例子更新了答案。希望对你有用。
    猜你喜欢
    • 2011-08-04
    • 1970-01-01
    • 2013-03-14
    • 1970-01-01
    • 2013-09-16
    • 2010-10-19
    • 1970-01-01
    • 1970-01-01
    • 2013-04-29
    相关资源
    最近更新 更多