2012-03-08 56 views
6

目前,我有以下代碼:是否有可能重構這個nHibernate的Linq查詢?

switch (publicationType) 
{ 
    case PublicationType.Book: 
     return Session.Query<Publication>() 
      .Where(p => p.PublicationType == PublicationType.Book) 
      .OrderByDescending(p => p.DateApproved)       
      .Take(10) 
      .Select(p => new PublicationViewModel 
      { 
       ... 
      }); 
    case PublicationType.Magazine: 
     return Session.Query<Publication>() 
      .Where(p => p.PublicationType == PublicationType.Magazine) 
      .OrderByDescending(p => p.DateApproved)       
      .Take(10) 
      .Select(p => new PublicationViewModel 
      { 
       ... 
      }); 
    case PublicationType.Newspaper 
    .... 
} 

正如你所看到的查詢是相同的除了publicationType條件各一次。我嘗試通過創建一個採用Func例如

private IEnumerable<PublicationViewModel> GetPublicationItems(Func<PublicationType, bool>> pubQuery) 
{ 
    return Session.Query<Publication>() 
     .Where(pubQuery)     
     .OrderByDescending(p => p.DateApproved)       
     .Take(10) 
     .Select(p => new PublicationViewModel 
     { 
      ... 
     });     
} 

private bool IsBook(PublicationType publicationType) 
{ 
    return publicationType == PublicationType.Book; 
} 

,然後調用此方法像

GetPublicationItems(IsBook); 

但是當我這樣做,我得到的錯誤: InvalidCastException的:無法投型「NHibernate.Hql.Ast.HqlParameter」的對象鍵入'NHibernate.Hql.Ast.HqlBooleanExpression'。

是否有另一種方法可以做到這一點?

回答

5

聽起來好像你並不真的需要一個功能 - 你只需要一個PublicationType

private IEnumerable<PublicationViewModel> 
    GetPublicationItems(PublicationType type) 
{ 
    return Session.Query<Publication>() 
     .Where(p => p.PublicationType == type) 
     .OrderByDescending(p => p.DateApproved)       
     .Take(10) 
     .Select(p => new PublicationViewModel 
     { 
      ... 
     });     
} 

如果你真的需要它比更一般的,你可能只需要改變你的代碼使用表達式樹,而不是委託(和改變輸入型):

private IEnumerable<PublicationViewModel> GetPublicationItems(
    Expression<Func<Publication, bool>> pubQuery) 
{ 
    return Session.Query<Publication>() 
     .Where(pubQuery)     
     .OrderByDescending(p => p.DateApproved)       
     .Take(10) 
     .Select(p => new PublicationViewModel 
     { 
      ... 
     });     
} 

您將無法與GetPublicationItems(IsBook)在這一點上,雖然調用它。你可以這樣做:

GetPublicationItems(p => p.PublicationType == PublicationType.Book) 

或者:

private static readonly Expression<Func<Publication, bool>> IsBook = 
    p => p.PublicationType == PublicationType.Book; 


... 

GetPublicationItems(IsBook) 
+0

真棒謝謝。我讓我的例子太簡單了,正如你所指出的,我可以直接將publicationType傳遞給查詢。但是你之後發佈的泛化正是我所追求的。 – Zac 2012-03-08 19:47:14

0

是否有一個原因,你不能只使用publicationType查詢?

return Session.Query<Publication>() 
     .Where(p => p.PublicationType == publicationType) 
     .OrderByDescending(p => p.DateApproved)       
     .Take(10) 
     .Select(p => new PublicationViewModel 
     { 
      ... 
     }); 
0

您的錯誤讓代表與表達式樹混淆。

Func是一個委託,它不能轉換爲SQL。 你可以只寫它,像這樣:

Session.Query<Publication>() 
.Where(p => p.PublicationType == yourPubilcationType) 
... 

或者,如果你想通過一個過濾器,方法,就像您在樣品中暗示:

IEnumerable<PublicationViewModel> GetPublicationItems(Expression<Func<PublicationType, bool>> pubQuery) 
{ 
    return Session.Query<Publication>() 
     .Where(pubQuery)     
     .OrderByDescending(p => p.DateApproved)       
     .Take(10) 
     .Select(p => new PublicationViewModel 
     { 
      ... 
     });     
}