C# NHibernate查询过滤器(按集合)

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.

我想通过使用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.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。