2017-03-14 10 views
1

Nhibernate를 사용하여 저장소 패턴을 사용하여 프로젝트를 개발 중입니다. Nhibernate에서 복잡한 결합을 수행하는 방법. 데이터를 가져 오는 데 저장소 방법을 사용하고 있습니다.NHibernate를 사용하여 리포지토리 패턴에서 복합 조인을 수행하는 방법?

public virtual TEntity FindBy(Expression<Func<TEntity, bool>> query) 
    { 
     try 
     { 
      return NHUnitOfWork.Session.Query<TEntity>().Where(query).FirstOrDefault(); 
     } 
     catch (Exception ex) 
     { 
      throw; 
     } 
    } 

여기서는 조인하지 않고 데이터를 가져올 수 있습니다. 조인을 사용하여 데이터를 가져 오는 방법은 무엇입니까? 예 : 메뉴 세부 정보가 메뉴 표에 저장되고 메뉴 권한이 메뉴 권한 표에 저장됩니다. 그것을위한 저장소를 만드는 방법?

답변

1

QueryOver을 사용하는 경우 FindBy 방법에 Expression 대신에 Junction 입력을 수락합니다.

다음 코드가 유용 할 수 있습니다. 필요하지 않은 경우 columnListtop 매개 변수를 제거하십시오. 내 ISession 사용법이 다릅니다. nhSessionNHUnitOfWork.Session으로 대체해야합니다. 또 다른 차이점은 Query을 사용하고 여기에 QueryOver을 사용하고 있다는 것입니다.

public virtual IList<T> FindBy<T>(ProjectionList columnList, Junction where, int top) where T : BaseEntity 
{ 
    IList<T> instance = GetQueryOver<T>(columnList, where).Take(top).List(); 
    return instance; 
} 

public virtual IQueryOver<T> GetQueryOver<T>(ProjectionList columnList, Junction where) where T : BaseEntity 
{ 
    IQueryOver<T> query = null; 
    if((columnList != null) && (where != null)) 
    { 
     query = nhSession.QueryOver<T>() 
       .Select(columnList) 
       .TransformUsing(Transformers.AliasToBean<T>()) 
       .Where(where); 
    } 
    else if((columnList != null) && (where == null)) 
    { 
     query = nhSession.QueryOver<T>() 
       .Select(columnList) 
       .TransformUsing(Transformers.AliasToBean<T>()); 
    } 
    else if((columnList == null) && (where != null)) 
    { 
     query = nhSession.QueryOver<T>() 
       .Where(where); 
    } 
    else 
    { 
     query = nhSession.QueryOver<T>(); 
    } 
    return query; 
} 

그리고, 당신은 같은 다른 위치에서이 호출 할 수 있습니다 : 당신이 열망로드 관련 기관에 FetchFetchMany을 사용하려면

Junction where = Restrictions.Conjunction(); 
where.Add(Restrictions.Eq(Projections.Property<MyEntity>(x => x.Field), findValue)); 
where.Add(Restrictions.................); 
where.Add(Restrictions.................); 
entityList = Repository.FindBy<MyEntity>(null, where, 100); 
+1

이 답변은이 질문에 맞습니까? 그는'QueryOver'가 아닌'Query'를 사용하고 있으며, 트랜스포머가 필요 없습니다. AutoMapper에서 'Select'또는 'ProjectTo'를 사용하면 쉽게 프로젝션을 수행 할 수 있습니다. – Rabban

1

.

public virtual Menu FindBy(Expression<Func<Menu, bool>> query) 
{ 
    return NHUnitOfWork.Session.Query<Menu>().Where(query) 
     .FetchMany(m => m.Rights) 
     // Required with FetchMany and First, otherwise only one right would be loaded. 
     .ToList() 
     .FirstOrDefault(); 
} 

또는 모델 메뉴 당 하나의 권리가있는 경우 :

public virtual Menu FindBy(Expression<Func<Menu, bool>> query) 
{ 
    return NHUnitOfWork.Session.Query<Menu>().Where(query) 
     .Fetch(m => m.Right) 
     .FirstOrDefault(); 
} 

을하지만 당신은 몇 가지 "일반적인 저장소"를 NHibernate에 API를 캡슐화를 정의 할 것 같다. 아마 다음
:

public virtual TEntity FindBy<TFetched>(Expression<Func<TEntity, bool>> query, 
    Expression<Func<TEntity, TFetched>> fetch) 
{ 
    var query = NHUnitOfWork.Session.Query<TEntity>().Where(query); 
    if (fetch != null) 
     query = query.Fetch(fetch); 
    return query 
     .FirstOrDefault(); 
} 

그러나 당신이 많은 페치을 *해야 할 경우 어떻게 할 :

public virtual TEntity FindBy<TFetched>(Expression<Func<TEntity, bool>> query, 
    Expression<Func<TEntity, IEnumerable<TFetched>>> fetchMany) 
{ 
    var query = NHUnitOfWork.Session.Query<TEntity>().Where(query); 
    if (fetchMany != null) 
     query = query.FetchMany(fetchMany); 
    return query 
     // Required with FetchMany and First, otherwise only one right would be loaded. 
     .ToList() 
     .FirstOrDefault(); 
} 

또는 모델 메뉴 당 하나의 권리가있는 경우

? 하위 가져 오기 ( ThenFetch/ ThenFetchMany)? 저주받은 길처럼 보입니다. 당신은 그 경로 다음에 전체 NHibernate API에 대한 캡슐화 코딩을 끝낼 수 있습니다.

사실, 공개적으로 Expression where 인수를 저장소에 표시하면 나에게 좋지 않습니다. 저장소는 데이터 조회 방법을 정의 할 책임이 없습니다.
원할 경우 IQueryable에 직접 노출하지 않으시겠습니까? 이 "저장소"외부에서 쿼리를 정의하면서 "저장소"에 캡슐화하려고 시도하는 것보다 코드를 상세하게 표현하는 것이 훨씬 적습니다.

* : 두 개 이상의 경우에 대비하여 카디 전 제품에주의하십시오. FetchMany. 이를 방지하려면 쿼리를 여러 개로 분할하거나 (DB 로의 단일 왕복을 원할 경우 ToFuture 사용) 반입하는 대신 lazy loading with batching을 사용하십시오.