是否有可能重构这个nHibernate Linq查询?

时间:2012-03-08 19:28:08

标签: c# linq nhibernate

目前我有以下代码:

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'。

还有其他办法吗?

3 个答案:

答案 0 :(得分: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)

答案 1 :(得分:0)

您是否有理由不能在查询中使用publicationType?

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

答案 2 :(得分: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
        {
            ...
        });                
}