我有一个“Estate”实体,这个实体有一个集合“EstateFeatures”(类型:EstateFeature),而EstateFeature有一个属性“MyFeatureValue”。
注意:这些是问题的有限属性。所有实体都有Id和所有necesarry等
遗产
IList<EstateFeature> EstateFeatures;
EstateFeature
FeatureValue MyFeatureValue;
FeatureValue
public virtual long Id;
我正在尝试获得具有给定FeatureValue.Id
的Real EstatesDetachedCriteria query = DetachedCriteria.For<Estate>();
Conjunction and = new Conjuction();
foreach (var id in idCollection)
and.Add(Expression.Eq("MyFeatureValue.Id",id);
query
.CreateCriteria("EstateFeatures")
.Add(and);
IList<Estate> estates = query.GetExecutableCriteria(session).List<Estate>();
此查询没有返回任何内容,我做错了什么?
由于
答案 0 :(得分:8)
如果我理解正确,我认为这样的事可能有效
CreateCriteria(typeof(Estate))
.CreateAlias("EstateFeatures", "estatefeature")
.Add(Restrictions.In("estatefeature.MyFeatureValue.Id", ids))
.List<Estate>();
答案 1 :(得分:2)
NHibernate为您生成了什么查询?您可以使用show_sql配置属性来检查这一点。
在我看到您的查询时,您正在尝试获取具有一组给定功能的所有Estates。 我想,这会产生一个看起来像
的查询SELECT ....
FROM Estates
INNER JOIN Features
WHERE Feature.Id = 1 AND Feature.Id = 2 ...
如果要检索包含所有指定功能的所有属性,我认为您必须使用Disjunction,以便NHibernate检索具有至少一个这些功能的所有Estates。
然后,在您的客户端代码中,您将检查“客户代码”中的每个Estate,以便最终最终获得具有所有功能的Estates。
我不知道是否有一种让NHibernate处理这个问题的有效方法......
答案 2 :(得分:2)
您需要确保为希望庄园拥有的每项功能加入MyFeatureValue一次。
一种方法是为每次迭代调用.CreateAlias,给它一个唯一的别名,然后添加表达式“aliasX.Id”
foreach (var id in idCollection) { query = query.CreateAlias("MyFeatureValue", "feature" + id) .Add(Expression.Eq("feature" + id + ".Id",id); }
我真的不记得语法是怎么回事了,写下这个,不确定你是否需要重新声明查询:)
但是,我认为这会让你开始。
编辑:由于Criteria API中的错误限制您使用CreateAlias或CreateCriteria多次关联集合,因此您需要求助于HQL。
http://derek-says.blogspot.com/2008/06/duplicate-association-path-bug-in.html
(Hibernate也遇到同样的问题)
select e FROM Estate AS e INNER JOIN e.MyFeatureValue AS fv1 INNER JOIN e.MyFeatureValue AS fv2 WHERE fv1.Id = 3 AND fv2.Id = 13
您需要动态构建HQL,以便您的别名变得唯一(fv1,fv2,fvX ......)
答案 3 :(得分:1)
代码看起来像是在传递一个FeaturesValueIds列表,并且想要一个具有所有这些功能的List。如果是这种情况,我会查看正在生成的SQL,并针对数据库运行它以查看是否应该返回任何内容。
否则,如果您正在寻找具有您传入的任何功能的List,则应使用Disjunction而不是Conjunction。
答案 4 :(得分:0)
exec sp_executesql N'SELECT TOP 3 id11_1_, Address11_1_, Title11_1_, Descript4_11_1_,
Price11_1_, Discount11_1_, ForBankL7_11_1_, AddDate11_1_, LastUpdate11_1_,
IsVisible11_1_, ViewCount11_1_, SaleOrRent11_1_, LocationId11_1_, StaffId11_1_,
CategoryId11_1_, id27_0_, EstateId27_0_, FeatureV3_27_0_ FROM (SELECT ROW_NUMBER()
OVER(ORDER BY __hibernate_sort_expr_0__) as row, query.id11_1_, query.Address11_1_,
query.Title11_1_, query.Descript4_11_1_, query.Price11_1_, query.Discount11_1_,
query.ForBankL7_11_1_, query.AddDate11_1_, query.LastUpdate11_1_, query.IsVisible11_1_,
query.ViewCount11_1_, query.SaleOrRent11_1_, query.LocationId11_1_, query.StaffId11_1_,
query.CategoryId11_1_, query.id27_0_, query.EstateId27_0_, query.FeatureV3_27_0_,
query.__hibernate_sort_expr_0__ FROM (SELECT this_.id as id11_1_, this_.Address as
Address11_1_, this_.Title as Title11_1_, this_.Description as Descript4_11_1_, this_.Price
as Price11_1_, this_.Discount as Discount11_1_, this_.ForBankLoan as ForBankL7_11_1_,
this_.AddDate as AddDate11_1_, this_.LastUpdate as LastUpdate11_1_, this_.IsVisible as
IsVisible11_1_, this_.ViewCount as ViewCount11_1_, this_.SaleOrRent as SaleOrRent11_1_,
this_.LocationId as LocationId11_1_, this_.StaffId as StaffId11_1_, this_.CategoryId as
CategoryId11_1_, estatefeat1_.id as id27_0_, estatefeat1_.EstateId as EstateId27_0_,
estatefeat1_.FeatureValueId as FeatureV3_27_0_, CURRENT_TIMESTAMP as
__hibernate_sort_expr_0__ FROM Estate this_ inner join EstateFeature estatefeat1_ on
this_.id=estatefeat1_.EstateId WHERE this_.CategoryId = @p0 and
(estatefeat1_.FeatureValueId = @p1 and estatefeat1_.FeatureValueId = @p2 and
estatefeat1_.FeatureValueId = @p3 and estatefeat1_.FeatureValueId = @p4 and
estatefeat1_.FeatureValueId = @p5 and estatefeat1_.FeatureValueId = @p6 and
estatefeat1_.FeatureValueId = @p7)) query ) page WHERE page.row > 0 ORDER BY
__hibernate_sort_expr_0__',N'@p0 bigint,@p1 bigint,@p2 bigint,@p3 bigint,@p4 bigint,@p5
bigint,@p6 bigint,@p7 bigint',@p0=3,@p1=7,@p2=8,@p3=9,@p4=10,@p5=11,@p6=12,@p7=16
答案 5 :(得分:0)
我也试过这个,但结果是一样的:
DetachedCriteria features = DetachedCriteria.For<FeatureValue>();
features.SetProjection(Projections.Property("Id"));
features.Add(Property.ForName("Id").EqProperty("value.Id"));
var and = new Conjunction();
foreach (var l in FeatureIdCollection)
and.Add(Expression.Eq("Id", l));
features.Add(and);
query.CreateCriteria("EstateFeatures")
.CreateCriteria("MyFeatureValue","value")
.Add(Subqueries.Exists(features));
答案 6 :(得分:0)
看起来您需要or
(Disjunction
)而不是and
(Conjunction
)。现在,您正在搜索EstateFeature
个对象,以便每个对象都有多个不同的Id
s,这似乎不是您想要的。
var or = new Disjunction();
foreach(var id in idCollection)
or.Add(Expression.Eq("MyFeatureValue.Id", id);
var query = DetachedCriteria.For<Estate>();
query
.CreateCriteria("EstateFeatures")
.Add(and);
var estates = query.GetExecutableCriteria(session).List<Estate>();