使用字典在 DataTable 上动态构建条件
Dynamically build a condition on a DataTable using a Dictionary
目前我可以这样查询我的 DataTable
(dtContacts):
如果我正在寻找 FirstName
是 "John" 且 LastName
是 "Smith" 的人。我的结果将是
DataTable dt = dtContacts.AsEnumerable().Where(c => c.Field<string>("FirstName") == "John" && c.Field<string>("LastName") == "Smith").CopyToDataTable();
但是这样的静态查询对我没有帮助,因为我的情况可能比这稍微复杂一些。所以我希望我的 LINQ 更动态一点,以便它可以适应以下场景。
我将像这样在 Dictionary<string,string>
中保存我的条件:
Dictionary<string, string> dicConditions = new Dictionary<string, string>();
dicConditions.Add("FirstName", "John");
dicConditions.Add("LastName", "Smith");
dicConditions.Add("IsCustomer", "Yes");
请注意,我们可以向该词典中添加任意数量的条件。
并且假设主 DataTable
dtContacts 始终包含字典键中提到的列名,因此我们不需要每次都检查它。
在新版本中,我们希望我们的 LINQ 根据 dicConditions
和 return 所有 FirstName
为 "John"、LastName
的值进行操作是 "Smith" 而 IsCustomer
是 "Yes".
这个新的动态 LINQ 查询应该是什么样子?
你可以这样做:
DataTable dt = dtContacts
.AsEnumerable()
.Where(c =>
dicConditions.All(kv => c.Field<string>(kv.Key) == kv.Value)
).CopyToDataTable();
想法是应用 LINQ 两次 - 一次应用到 dtContacts
,一次应用到 Where
子句内的 dicConditions
。
您可以使用如下方法从字典构建上面显示的谓词:
using StringKvp = System.Collections.Generic.KeyValuePair<string, string>;
using DataRowPredicate = System.Func<System.Data.DataRow, bool>;
...
var pred = dicConditions.Aggregate<StringKvp, DataRowPredicate>(r => true,
(net, curr) => r => net(r) && r.Field<string>(curr.Key) == curr.Value);
然后只需使用此谓词过滤您的集合即可:
var dt = dtContacts.AsEnumerable().Where(pred).CopyToDataTable();
像这样...
var result= dtContacts.Rows.OfType<DataRow>().Where(r=>dicConditions.All(d=>r[d.key]==d.Value));
您可能需要正确转换字典的值以与数据表兼容...
使用 Regex 支持通配符...等...
目前我可以这样查询我的 DataTable
(dtContacts):
如果我正在寻找 FirstName
是 "John" 且 LastName
是 "Smith" 的人。我的结果将是
DataTable dt = dtContacts.AsEnumerable().Where(c => c.Field<string>("FirstName") == "John" && c.Field<string>("LastName") == "Smith").CopyToDataTable();
但是这样的静态查询对我没有帮助,因为我的情况可能比这稍微复杂一些。所以我希望我的 LINQ 更动态一点,以便它可以适应以下场景。
我将像这样在 Dictionary<string,string>
中保存我的条件:
Dictionary<string, string> dicConditions = new Dictionary<string, string>();
dicConditions.Add("FirstName", "John");
dicConditions.Add("LastName", "Smith");
dicConditions.Add("IsCustomer", "Yes");
请注意,我们可以向该词典中添加任意数量的条件。
并且假设主 DataTable
dtContacts 始终包含字典键中提到的列名,因此我们不需要每次都检查它。
在新版本中,我们希望我们的 LINQ 根据 dicConditions
和 return 所有 FirstName
为 "John"、LastName
的值进行操作是 "Smith" 而 IsCustomer
是 "Yes".
这个新的动态 LINQ 查询应该是什么样子?
你可以这样做:
DataTable dt = dtContacts
.AsEnumerable()
.Where(c =>
dicConditions.All(kv => c.Field<string>(kv.Key) == kv.Value)
).CopyToDataTable();
想法是应用 LINQ 两次 - 一次应用到 dtContacts
,一次应用到 Where
子句内的 dicConditions
。
您可以使用如下方法从字典构建上面显示的谓词:
using StringKvp = System.Collections.Generic.KeyValuePair<string, string>;
using DataRowPredicate = System.Func<System.Data.DataRow, bool>;
...
var pred = dicConditions.Aggregate<StringKvp, DataRowPredicate>(r => true,
(net, curr) => r => net(r) && r.Field<string>(curr.Key) == curr.Value);
然后只需使用此谓词过滤您的集合即可:
var dt = dtContacts.AsEnumerable().Where(pred).CopyToDataTable();
像这样...
var result= dtContacts.Rows.OfType<DataRow>().Where(r=>dicConditions.All(d=>r[d.key]==d.Value));
您可能需要正确转换字典的值以与数据表兼容...
使用 Regex 支持通配符...等...