문제

"부동산" 엔터티가 있고 이 엔터티에는 "EstateFeatures"(유형:EstateFeature) 컬렉션이 있고 EstateFeature에는 "MyFeatureValue" 속성이 있습니다.

메모:이는 질문의 제한된 속성입니다.모든 엔터티에는 ID와 필요한 모든 항목이 있습니다.

사유지

IList<EstateFeature> EstateFeatures;

부동산특징

FeatureValue MyFeatureValue;

기능값

public virtual long Id;

주어진 FeatureValue.Id를 가진 부동산을 얻으려고 합니다.

DetachedCriteria 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>();

이 쿼리에서 아무것도 반환되지 않았습니다. 제가 뭔가 잘못하고 있는 걸까요?

감사해요

도움이 되었습니까?

해결책

귀하는 귀하의 부동산에 부여하려는 각 기능에 대해 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 ...).

다른 팁

내가 올바르게 이해한다면 이런 것이 효과가 있다고 생각합니다

CreateCriteria(typeof(Estate))
     .CreateAlias("EstateFeatures", "estatefeature")
     .Add(Restrictions.In("estatefeature.MyFeatureValue.Id", ids))
     .List<Estate>();

nhibernate가 당신을 위해 어떤 쿼리를 생성 했습니까? show_sql config 속성을 사용하여 확인할 수 있습니다.

쿼리를 볼 때 주어진 기능 세트가있는 모든 부동산을 얻으려고합니다. 나는 이것이 보이는 쿼리를 생성 할 것이라고 생각합니다.

SELECT ....
FROM Estates
INNER JOIN Features
WHERE Feature.Id = 1 AND Feature.Id = 2 ...

지정된 모든 기능이 포함 된 모든 부동산을 검색하려면 분리를 사용해야한다고 생각하여 Nhibernate는 이러한 기능 중 하나 이상이있는 모든 부동산을 검색합니다. 그런 다음 클라이언트 코드에서 '클라이언트 코드'의 모든 부동산을 검사하여 결국 모든 기능이있는 부동산으로 끝납니다.
nhibernate가 이것을 처리 할 수있는 효율적인 방법이 있는지 모르겠습니다 ...

이 코드는 FeationsValueids 목록을 전달하고 있으며 이러한 모든 기능이있는 목록을 원하는 것처럼 보입니다. 이 경우 생성되는 SQL을 살펴보고 데이터베이스에 대해 실행하여 무엇이든 되돌려야하는지 확인합니다.

그렇지 않으면, 당신이 통과하는 기능이있는 목록을 찾고 있다면, 당신은 결합 대신 분리를 사용해야합니다.

    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

당신이 원하는 것 같습니다 or (Disjunction) 대신에 and (Conjunction). 지금, 당신은 찾고 있습니다 EstateFeature각 객체의 여러 가지가 있도록 S 객체 IdS, 당신이 원하는 것이 아닌 것 같습니다.

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>();

나는 또한 이것을 시도했지만 결과는 동일합니다.

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));
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top