C# LINQ谓词中使用的集合的范围
我真的很喜欢。它允许我非常动态地构建各种查询。谓词变量可以传递给不同的对象,它们可以使用它们知道的值等添加到谓词变量中,除非我需要在散列集合上使用.Contains。Bzzt!碰撞和燃烧 例如(示例/伪代码,可能编译/运行,也可能不编译/运行):C# LINQ谓词中使用的集合的范围,c#,linq-to-sql,predicatebuilder,C#,Linq To Sql,Predicatebuilder,我真的很喜欢。它允许我非常动态地构建各种查询。谓词变量可以传递给不同的对象,它们可以使用它们知道的值等添加到谓词变量中,除非我需要在散列集合上使用.Contains。Bzzt!碰撞和燃烧 例如(示例/伪代码,可能编译/运行,也可能不编译/运行): 受保护的表达式GetWherePredicate() { string[]selectedValues=Request.Form.GetValues(“复选框1”)??新字符串[0]; HashSet selectedds=新的HashSet(sele
受保护的表达式GetWherePredicate()
{
string[]selectedValues=Request.Form.GetValues(“复选框1”)??新字符串[0];
HashSet selectedds=新的HashSet(selectedValues.Cast());
表达式谓词=PredicateBuilder.True();
谓词=谓词。和(s=>selectedIDs.Contains(s.ID));
返回谓词;
}
受保护的void检索()
{
表达式谓词=GetWherePredicate();
IEnumerable retrievedValues=MyDataContext.GetTable.Where(谓词);
}
当我尝试这样做时,我得到一个NotSupportedException:Method'Boolean Contains(Int32)'不支持转换为SQL,因为SelectedDS哈希集不在范围内。如果我用同样的方法做这一切,那么效果很好
我需要知道正确的方法,让我的谓词在那里解析、编译或其他任何东西,以便它可以在声明HashSet的不同范围内使用。有什么帮助吗
更新:我把这件事搞错了。下面的代码工作正常,因此没有范围冲突。谢谢你,杰
string[] selectedValues = Request.Form.GetValues("checkbox1") ?? new string[0];
Expression<Func<MyClass, bool>> predicate = PredicateBuilder.True<MyClass>();
predicate = predicate.And(s => selectedValues.Contains(s.ID.ToString()));
string[]selectedValues=Request.Form.GetValues(“checkbox1”)??新字符串[0];
表达式谓词=PredicateBuilder.True();
predicate=predicate.And(s=>selectedValues.Contains(s.ID.ToString());
从您引用的例外情况来看,范围似乎不太可能是一个因素
我的答案是,您需要将selectedIDs
声明为IEnumerable
,而不是HashSet
(或者在调用Contains()
之前强制转换它),但这并不能解释它在使用相同方法时是否工作,因此我不确定
如果看不到任何实际的代码表现出这种行为,就很难进一步排除故障。不要被
包含的名称弄得眼花缭乱。
有许多方法都被命名为该方法,并且没有多少方法支持转换为SQL
和Enumerable.Contains
是支持翻译的方法List.Contains
是一个不支持翻译的方法HashSet.Contains
有很多决议,但我建议:
IEnumerable<string> selectedValueQuery =
Request.Form.GetValues("checkbox1") ?? Enumerable.Empty<string>();
List<string> selectedIds = selectedValueQuery
.Cast<int>()
.Distinct()
.ToList();
IEnumerable selectedValueQuery=
Request.Form.GetValues(“checkbox1”)??Enumerable.Empty();
列表SelectedDS=selectedValueQuery
.Cast()
.Distinct()
.ToList();
尽管更简单的解决方案可能是:
IEnumerable<int> selectedIDs = new HashSet<int>(selectedValues.Cast<int>());
IEnumerable selectedIDs=新哈希集(selectedValues.Cast());
编辑:这根本不是关于包含的具体实现,而是关于linqtosql查询提供程序是否能够识别该方法并将其转换为IN(列表)sql表达式。识别代码查看表达式中使用的参数的类型。识别代码不使用多态性/实现,也不在继承树中查找其他可能性
List<int> myList = new List<int>(){1, 2, 3};
IList<int> myIList = myList;
IEnumerable<int> myIEnumerable = myList;
//works by List<T>.Contains()
db.Customers.Where(c => myList.Contains(c.CustomerID));
//doesn't work, no translation for IList<T>.Contains
db.Customers.Where(c => myIList.Contains(c.CustomerID));
//works by Enumerable.Contains<T>()
db.Customers.Where(c => myIEnumerable.Contains(c.CustomerID));
//works by Enumerable.Contains<T>()
db.Customers.Where(c => Enumerable.Contains(myIEnumerable, c.CustomerID));
List myList=newlist(){1,2,3};
IList myIList=myList;
IEnumerable myIEnumerable=myList;
//按列表工作。包含()
其中(c=>myList.Contains(c.CustomerID));
//不起作用,没有IList的翻译。包含
其中(c=>myIList.Contains(c.CustomerID));
//按可枚举项工作。包含()
其中(c=>myIEnumerable.Contains(c.CustomerID));
//按可枚举项工作。包含()
其中(c=>Enumerable.Contains(myIEnumerable,c.CustomerID));
即使这些参数引用了相同的实例,但由于参数的类型不同,也会出现不同的转换行为
.Contains()
在翻译时不被调用,因此它的实现是不相关的。它可以抛出NotImplementedException
或返回true;
好的,我会仔细研究一下我的代码,看看我是否走错了路。谢谢。很好,谢谢。我花了一些时间阅读了IEnumerable.Contains之间的区别还有IList.Contains,我想这可能是我一开始讨论的核心问题。所以你推荐的类型都是很好的指南。IList.Contains没有支持的翻译。List.Contains有。没有IEnumerable.Contains这样的东西。这是一个随意的评论,我是根据记忆写名字的。我没有试图为人们记录东西。有时es这个网站和其他任何东西一样让我烦恼…/叹气,我通常不会对class.methods名称这么敏感,但这是导致原始问题的原因。我不认为这是松弛。这是缺乏知识。现在我知道IEnumerable有Enumerable。包含与LINQ一起工作的扩展方法。HashSet实现了I实现ICollection的列表,它有一个Contains方法,不能与LINQ一起工作。所以从技术上来说,你和你说的我一样不正确,这很讽刺,你不觉得吗?
List<int> myList = new List<int>(){1, 2, 3};
IList<int> myIList = myList;
IEnumerable<int> myIEnumerable = myList;
//works by List<T>.Contains()
db.Customers.Where(c => myList.Contains(c.CustomerID));
//doesn't work, no translation for IList<T>.Contains
db.Customers.Where(c => myIList.Contains(c.CustomerID));
//works by Enumerable.Contains<T>()
db.Customers.Where(c => myIEnumerable.Contains(c.CustomerID));
//works by Enumerable.Contains<T>()
db.Customers.Where(c => Enumerable.Contains(myIEnumerable, c.CustomerID));