3

나는 최근에 NHibernate를 시작했고, 더 자세히 설명 된 도메인 모델을 구현하는 데 어려움을 겪고있다.다중 조인이 필요한 쿼리에서 Fluent NHibernate와 일대 다 관계를 필터링하고 있습니까?

내가 찾고있는 것은 특정 DataStores에서 Item과 ItemData 컬렉션 간의 관계를 필터링하는 방법입니다. 데이터 저장소는 전역이거나, 항상 반환되거나 사용자 ID (응용 프로그램 인스턴스에 기반)에 따라 다릅니다.

SELECT * FROM Items i 
INNER JOIN ItemData id ON (i.ItemId=id.ItemId) 
LEFT OUTER JOIN Users u ON (id.UserId=u.UserId) 
LEFT OUTER JOIN DataStore ds ON (id.DataStoreId=ds.DataStoreId) 
WHERE ds.IsGlobal = 1 OR ds.UserId = @userId 

데이터베이스 구조 :

DataStore: 
- DataStoreId (PK) 
- Name 
- Weight 
- UserId 
- IsGlobal 

Item: 
- ItemId (PK) 
- ... (non-nullable fields) 

ItemData: 
- ItemDataId (PK) 
- ItemId 
- DataStoreId 
- ... (nullable fields) 

도메인 모델 :

public class ItemMap : ClassMap<Item> 
{ 
    public ItemMap() 
    { 
     Id(x => x.Id, "ItemId"); 
     HasMany(x => x.Data) 
      .KeyColumn("ItemId") 
      .ApplyFilter<ItemDataFilter>(..?) 
      .Cascade.AllDeleteOrphan(); 
    } 
} 

기본 이론을 가져 오기 위해 하나 정보 ItemData

는 SQL 이것은 간단한 쿼리를 사용하여 수행 할 수 있습니다 DataStore 당 하나의 행을 만들고 각 데이터 저장소의 가중치 필드에있는 각 열을 결합합니다 (첫 번째 null이 아닌 val 무게에 따라 정렬).

통찰력에 관해서는 NHibernate에서 이것이 어떻게 달성 될 수 있었는지에 대해 많이 감사하겠습니다.

답변

5

Heres 다른 사람이이 정보를 찾고있는 경우에 대비해.

1.Create 사용자 정의 필터 :

public class ItemDataFilter : FilterDefinition 
{ 
    public ItemDataFilter() 
    { 
     WithName("ItemDataFilter").WithCondition("Data.DataStoreId == :DataStoreId").AddParameter("DataStoreId", NHibernate.NHibernateUtil.Int32); 
    } 
} 

2.Modify 당신의 유창함 NHibernate에 속성 매핑 (.ApplyFilter <로>()) :

HasMany(x => x.Data) 
    .KeyColumn("ItemId") 
    .ApplyFilter<ItemDataFilter>() 
    .Cascade.AllDeleteOrphan(); 

3.In 저장소가 가능 필터를 설정하고 현재 세션의 속성을 설정하십시오.

public IList<Item> GetItemsByDataStore(int DataStoreId) 
    { 
    using (var session = NHibernateHelper.OpenSession()) 
    { 
     session.EnableFilter("ItemDataFilter").SetParameter("DataStoreId", DataStoreId); 
     return session.CreateCriteria(typeof(Item)).List<Item>(); 
    } 
} 

다른 방법 이것은 각 Item에 대한 모든 ItemData를 가져와이 필터링을 수행하는 매핑되지 않은 다른 속성을 추가하는 것입니다.

1

너무 간단한 쿼리를 사용하여이 사용 HQL을 수행 할 수 있습니다 .. 다음과 같이 귀하의 HQL 쿼리 구문은 다음과 같습니다

var hqlQuery= string.Format("select i from Items as i inner join i.ItemData left join Users u left join DataStire ds where u.UserId=i.UserId and ds.DataStoreId=i.DataStoreId and (ds.IsGlobal=1 or ds.UserId='{0}')",userId); 

Session.CreateQuery(hqlQuery).List<Item>(); 

희망이 작품 :

Session.CreateQuery(hqlQuery).List(); 

당신의 hqlQuery은 다음과 같이 될 것입니다 ..

+0

감사합니다.하지만이 관계가 사용자 지정 쿼리가 아닌 모델의 일부로 표현되기를 바랍니다. 예를 들어 Item을 가져 오는 경우 ItemData 컬렉션을 다시 가져올 필요없이이 규칙을 사용하여 필터링해야합니다. – magix

+0

잘 당신은 항상 같은 문장을 추가 할 수 있습니다. stringbuilder 클래스를 만들고 기본 구문을 추가 한 다음 원하는 경우 필터링 조건과 ur 조건을 where 절에 추가하십시오. – Baz1nga

관련 문제