2012-03-08 35 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 
     { 
      ... 
     });     
}