C# NHibernate查询过滤器(按集合)
我想通过使用nHhibernate的内存集合过滤db表(具有复合键Id1和Id2)C# NHibernate查询过滤器(按集合),c#,linq,nhibernate,linq-to-nhibernate,C#,Linq,Nhibernate,Linq To Nhibernate,我想通过使用nHhibernate的内存集合过滤db表(具有复合键Id1和Id2) class Item{ int Id1; int Id2; } var collection = new List<Item>(); var list = _session .QueryOver<MyDbTable>() .Where(x => collection.Any(y => y.Id1 == x.Id1 && y.Id2 == x.
class Item{ int Id1; int Id2; }
var collection = new List<Item>();
var list = _session
.QueryOver<MyDbTable>()
.Where(x => collection.Any(y => y.Id1 == x.Id1 && y.Id2 == x.Id2))
.List();
类项{int-Id1;int-Id2;}
var collection=新列表();
变量列表=\u会话
.QueryOver()
.Where(x=>collection.Any(y=>y.Id1==x.Id1&&y.Id2==x.Id2))
.List();
我通过这样做得到的错误是“无法识别的方法调用:System.Linq.Enumerable:Boolean Any”。我还尝试使用FirstOrDefault方法并将结果与null进行比较,但没有效果。您不能在NHibernate中使用Linq方法 如果要验证属性是否在集合中,可以使用
IsIn
方法,但在您的情况下,我们不想检查集合中是否有单个属性,我们正在寻找复合键
为了解决您的问题,您可以迭代集合
来构造您的限制:
var disjunctionOptions = new Disjunction();
foreach (var item in collection)
{
var conjunction = new Conjunction();
conjunction.Add<MyDbTable>(x => x.Id1 == item.Id1);
conjunction.Add<MyDbTable>(x => x.Id2 == item.Id2);
disjunctionOptions.Add(conjunction);
}
var list = _session
.QueryOver<MyDbTable>()
.Where(disjuntionOptions)
.List();
var析取选项=新析取();
foreach(集合中的var项)
{
var连接=新连接();
连接词.Add(x=>x.Id1==item.Id1);
连接词.Add(x=>x.Id2==item.Id2);
析取选项。添加(连词);
}
变量列表=\u会话
.QueryOver()
.其中(disjuntionOptions)
.List();
这样,您就可以使用复合键获得正确的查询结果
注意:IsIn
用于检查集合(或数组)中是否存在单个属性。如果单独使用(在每个属性中),它将给出错误的结果,因为您使用的是复合键
不能在NHibernate中使用Linq方法 如果要验证属性是否在集合中,可以使用
IsIn
方法,但在您的情况下,我们不想检查集合中是否有单个属性,我们正在寻找复合键
为了解决您的问题,您可以迭代集合
来构造您的限制:
var disjunctionOptions = new Disjunction();
foreach (var item in collection)
{
var conjunction = new Conjunction();
conjunction.Add<MyDbTable>(x => x.Id1 == item.Id1);
conjunction.Add<MyDbTable>(x => x.Id2 == item.Id2);
disjunctionOptions.Add(conjunction);
}
var list = _session
.QueryOver<MyDbTable>()
.Where(disjuntionOptions)
.List();
var析取选项=新析取();
foreach(集合中的var项)
{
var连接=新连接();
连接词.Add(x=>x.Id1==item.Id1);
连接词.Add(x=>x.Id2==item.Id2);
析取选项。添加(连词);
}
变量列表=\u会话
.QueryOver()
.其中(disjuntionOptions)
.List();
这样,您就可以使用复合键获得正确的查询结果
注意:IsIn
用于检查集合(或数组)中是否存在单个属性。如果单独使用(在每个属性中),它将给出错误的结果,因为您使用的是复合键
当你相信自己在使用时,可能会感到困惑和使用。在这种情况下,要使用linq2nh,请将代码更改为:
using NHibernate.Linq;
...
var collection = new List<Item>();
var list = _session
.Query<MyDbTable>()
.Where(x => collection.Any(y => y.Id1 == x.Id1 && y.Id2 == x.Id2))
.ToList();
使用NHibernate.Linq;
...
var collection=新列表();
变量列表=\u会话
.Query()
.Where(x=>collection.Any(y=>y.Id1==x.Id1&&y.Id2==x.Id2))
.ToList();
将
QueryOver
切换到Query
时需要using
,因为ISession.Query
是在NHibernate.Linq
命名空间中定义的扩展方法。使用Linq API而不是QueryOver
,必须将List
方法调用更改为ToList
,可能您在相信自己在使用时感到困惑和使用。在这种情况下,要使用linq2nh,请将代码更改为:
using NHibernate.Linq;
...
var collection = new List<Item>();
var list = _session
.Query<MyDbTable>()
.Where(x => collection.Any(y => y.Id1 == x.Id1 && y.Id2 == x.Id2))
.ToList();
使用NHibernate.Linq;
...
var collection=新列表();
变量列表=\u会话
.Query()
.Where(x=>collection.Any(y=>y.Id1==x.Id1&&y.Id2==x.Id2))
.ToList();
将
QueryOver
切换到Query
时需要using
,因为ISession.Query
是在NHibernate.Linq
命名空间中定义的扩展方法。使用Linq API而不是QueryOver
,List
方法调用必须更改为ToList
,我同意我的版本不起作用,但无论如何我肯定会寻找另一个解决方案。当集合有一些合适的大小(如100个元素)或可能是1000个元素时,您是否意识到析取查询生成的SQL的大小?Hi@AlexeyZimarev,SQL查询长度的限制是65536*网络数据包大小(默认为4KB)。2100个参数的限制将超过SQL查询长度之前的限制。例如,不能使用包含2100个以上元素的集合来使用IsIn。这不是我的解决方案中的一个特殊问题,在这种情况下,我使用的是最小数量的参数。我同意我对ands和ors的查询会更长,但不会增加参数的数量。当然,必要时可以使用HQL。我同意我的版本不起作用,但无论如何我肯定会寻找另一种解决方案。当集合有一些合适的大小(如100个元素)或可能是1000个元素时,您是否意识到析取查询生成的SQL的大小?Hi@AlexeyZimarev,SQL查询长度的限制是65536*网络数据包大小(默认为4KB)。2100个参数的限制将超过SQL查询长度之前的限制。例如,不能使用包含2100个以上元素的集合来使用IsIn。这不是我的解决方案中的一个特殊问题,在这种情况下,我使用的是最小数量的参数。我同意我对ands和ors的查询会更长,但不会增加参数的数量。当然,必要时可以使用HQL。