2011-01-21 77 views
1

我想爲nHibernate和QueryOver創建List()的泛型方法。我已經達到了想要添加連接的程度,但是如果沒有指定我要加入的泛型類型,我不認爲我可以這樣做......這不會使它變得如此動態,因爲每個泛型都必須聲明。有沒有任何地方可以有一個動態的連接列表?代碼如下: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.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); 

(請注意我指定LEFT JOIN明確地說 - 如果你想要這個可控制的話,你必須把它作爲Tuple中的一個附加參數添加進去)

現在看起來相當複雜,但是一旦你把它放在一起就相當簡單了。您當然可以創建幫助器方法來減少代碼中'Func'垃圾的數量。

希望有幫助!


空helper方法:

public static class Null 
{ 
    public static T Get<T>() 
    { 
     return default(T); 
    } 
}