我使用PredicateBuilder创建一个动态Where子句来从DataTable查询数据。我有一个字典,其中包含我需要搜索的列名和值。我只是在字典上迭代,如果键匹配列名,那么将该键和值添加到谓词中。一切似乎都很好,直到对数据表运行实际查询,我得到零记录返回:(但是,如果我用p => p["Year"]=="2010"之类的东西替换动态谓词,我得到记录返回。下面是代码:
var objectList = table.AsEnumerable();
Func<DataRow, bool> predicate = GetPredicate(parms, table.Columns);
var list1 = objectList.Where(predicate).ToList();
private static Func<DataRow, bool> GetPredicate(Dictionary <string, string> parms, DataColumnCollection dataColumnCollection)
{
var predicate = PredicateBuilder.False<DataRow>();
foreach (var parm in parms)
{
if (dataColumnCollection.Contains(parm.Key))
{
var copy = parm;
predicate = predicate.And(p => p[copy.Key] == copy.Value);
}
}
return predicate.Compile();
}
您从false
开始,然后添加and
子句。
false && ...
总是返回false
,所以你的Where
子句永远不会匹配任何东西。
试着以:
开头var predicate = PredicateBuilder.True<DataRow>();
也
:
您正在关闭一个循环变量,这意味着您的所有谓词将使用parms
中的最后一个parm
。
你可以通过在循环中创建一个本地副本来解决这个问题:
foreach( var parm in parms )
{
if (dataColumnCollection.Contains(parm.Key))
{
var copy = parm;
predicate = predicate.And( p => p[ copy.Key ] == copy.Value );
}
更新:
DataRow[ key ]
的类型是object
,因此在p[ copy.Key ] == copy.Value
中,相等操作符是对象引用相等,而不是字符串相等。
可以通过指定String.Equals
:
predicate = predicate.And( p => String.Equals( p[ copy.Key ], copy.Value ) );
有趣的是,这个例子显示了可以有多个具有相同内容的string
实例。