2011-01-21 3 views
1

Я хочу создать общий метод для List() с nHibernate и QueryOver. У меня есть это до такой степени, что я хотел бы добавить объединения, но я не думаю, что могу, не указывая общий тип, с которым я вхожу ... Что не делает его настолько динамичным, потому что каждый родословный должен быть объявлен. Есть ли где-нибудь динамический список соединений? Код ниже:nHibernate Динамические соединения с QueryOver

public static IList<T> QueryOver<T>(
     Dictionary<Expression<Func<T, object>>, JoinType> joins, 
     List<Expression<Func<T, bool>>> predicates, 
     Dictionary<Expression<Func<T, object>>, System.Web.UI.WebControls.SortDirection> sortList, 
     int? maxResults 
    ) where T : class 
    { 
     IList<T> results; 
     IQueryOver<T, T> query; 

     results = null; 

     // open the session 
     using (ISession session = OpenSession()) 
     { 
      // begin a transaction 
      using (ITransaction transaction = session.BeginTransaction()) 
      { 
       try 
       { 
        // declare the query 
        query = session.QueryOver<T>(); 

        // joins 
        if (joins != null && joins.Count > 0) 
        { 
         foreach (KeyValuePair<Expression<Func<T, object>>, JoinType> join in joins) 
         { 
          // required to specify the type in the format query.JoinQueryOver<SubType>(join.Key, join.Value) 
          // BUT this means that it's not so dynamic because each SubType would have to be specified in the method call, yes? 
          query = query.JoinQueryOver(join.Key, join.Value); 
         } 
        } 

        // apply the where clauses 
        if (predicates != null && predicates.Count > 0) 
        { 
         foreach (Expression<Func<T, bool>> predicate in predicates) 
         { 
          query = query.Where(predicate); 
         } 
        } 

        // apply the sorting 
        if (sortList != null && sortList.Count > 0) 
        { 
         foreach (KeyValuePair<Expression<Func<T, object>>, System.Web.UI.WebControls.SortDirection> sort in sortList) 
         { 
          if (sort.Value == System.Web.UI.WebControls.SortDirection.Ascending) 
          { 
           query = query.OrderBy(sort.Key).Asc; 
          } 
          else 
          { 
           query = query.OrderBy(sort.Key).Desc; 
          } 
         } 
        } 

        // max results 
        if (maxResults.HasValue && maxResults.Value > 0) 
        { 
         query = (IQueryOver<T, T>)query.Take(maxResults.Value); 
        } 

        results = query.List(); 

        // no errors, commit the transaction 
        transaction.Commit(); 
       } 
       catch (Exception ex) 
       { 
        // error, rollback 
        transaction.Rollback(); 

        // throw the exception and let the business logic deal with it 
        throw ex; 
       } 
      } 
     } 

     return results; 
    } 

ответ

1

Посмотрите на использование JoinAlias ​​вместо JoinQueryOver ..., который должен вам помочь.

Существует два вида объединений: прямые соединения на объекте типа T и непрямые объединения (два или более шагов). Они требуют разных подходов.

(1) Для прямого присоединяется, ваш метод может получить IEnumerable типа (готовый к ней):

Tuple<Expression<Func<T, object>>, Expression<Func<object>>> 

примером которого может выглядеть в коде вызова:

JoiningEntity joiningEntity = null; 
new Tuple<Expression<Func<YourEntityType, object>>, Expression<Func<object>>>(entity => entity.JoiningEntity,() => joiningEntity) 

Нулевой объект - это просто псевдоним, чтобы QueryOver мог его разрешить. Вы можете получить раздражение от предупреждений в Visual Studio, говорящих вам, что это null, поэтому я бы использовал вспомогательный метод для создания нулевых объектов, например. Null.Get<HolidayOccupancyPrice>() (см. Нижний для метода нулевого помощника).

(2) Для непрямого присоединяется, вам необходимо пройти в IEnumerable типа:

Tuple<Expression<Func<object>>, Expression<Func<object>>> 

т.е., как указано выше, но без типа сущностей. И тогда ваш вызывающий код может отправить присоединиться как это:

JoiningEntity joiningEntity = null; 
new Tuple<Expression<Func<object>>, Expression<Func<object>>>(() => joiningEntity.IndirectJoiningEntity,() => joiningEntity) 

Собирает вместе в методе запроса, вы хотите что-то вроде этого:

IEnumerable<Tuple<Expression<Func<T, object>>, Expression<Func<object>>>> directJoins; 
IEnumerable<Tuple<Expression<Func<object>>, Expression<Func<object>>>> indirectJoins; 
// .... 
foreach (var join in directJoins) 
    query = queryable.Left.JoinAlias(dependency.Item1, dependency.Item2); 
foreach (var join in indirectJoins) 
    query = queryable.Left.JoinAlias(dependency.Item1, dependency.Item2); 

(Заметьте, я указал левый присоединиться явно - если вы хотите, чтобы этот управляемый вам нужно было добавить в качестве дополнительного параметра в Tuple)

Теперь все это выглядит довольно сложно, но его довольно прямолинейно, как только вы его соедините. Разумеется, вы можете создать вспомогательные методы, чтобы уменьшить количество «Func» в вашем коде.

Надеюсь, что это поможет!


Null вспомогательный метод:

public static class Null 
{ 
    public static T Get<T>() 
    { 
     return default(T); 
    } 
} 
Смежные вопросы