在工厂中为NHibernate QueryOver Where子句生成LINQ表达式

时间:2011-06-24 01:51:02

标签: c# linq nhibernate refactoring queryover

我有一个支持基于多个标识符查询的数据源。这些标识符由IIdentifier类抽象,该类包装查询的类型和值。在我的NHibernate DAO中,我有以下方法。

public IEnumerable<ICustomerProfileAttribute> GetCustomerProfileAttributes(
    IIdentifier<CustomerIdentifierTypeEnum> identifier, IEnumerable<string> attributeNames)
{
    IList<ICustomerProfileAttribute> customerProfileAttributes = new List<ICustomerProfileAttribute>();

    ICustomerProfile customerProfileAlias = null;
    ICustomerProfileAttribute customerProfileAttributeAlias = null;
    IEntityTypeAttribute entityTypeAttribute = null;
    IAttribute attributeAlias = null;

    Expression<Func<bool>> findCustomerProfileQuery;
    // I would like to replace the switch with something like this:
    // = FindCustomerProfileExpressionFactory.Get(customerProfileAlias, identifier); 

    switch (identifier.IdentifierType)
    {
        case CustomerIdentifierTypeEnum.CustomerNumber:
            findCustomerProfileQuery = () => customerProfileAlias.CustomerNumber == identifier.Value.ToString();
            break;
        case CustomerIdentifierTypeEnum.WebAccount:
            findCustomerProfileQuery = () => customerProfileAlias.WebAccountId == (long)identifier.Value;
            break;
        case CustomerIdentifierTypeEnum.WebLogin:
            findCustomerProfileQuery = () => customerProfileAlias.LoginEmailAddress == identifier.Value.ToString();
            break;
        default:
            throw new NotImplementedException(String.Format("lookup of customer profiles using {0} is not supported", identifier.IdentifierType));
    }

    return Session.QueryOver(() => customerProfileAttributeAlias)
        .JoinAlias(() => customerProfileAttributeAlias.CustomerProfile, () => customerProfileAlias,
                    JoinType.LeftOuterJoin)
        .Where(findCustomerProfileQuery)
        .JoinAlias(() => customerProfileAttributeAlias.EntityTypeAttribute, () => entityTypeAttribute,
                    JoinType.LeftOuterJoin)
        .JoinAlias(() => entityTypeAttribute.Attribute, () => attributeAlias, JoinType.LeftOuterJoin)
        .Where(Restrictions.On(() => attributeAlias.Name).IsIn(attributeNames.ToArray()))
        .List<ICustomerProfileAttribute>();
}

我想将switch语句解压缩到工厂类中,因为它在我的应用程序的其他几个部分中很有用。我尝试了以下方法:

class FindCustomerProfileExpressionFactory
    {
        static public Expression<Func<bool>> Get(ICustomerProfile profile, IIdentifier<CustomerIdentifierTypeEnum> identifier)
        {
            switch (identifier.IdentifierType)
            {
                case CustomerIdentifierTypeEnum.CustomerNumber:
                    return () => customerProfileAlias.CustomerNumber == identifier.Value.ToString(); 
             ...

但是,通过引用工厂类,我将局部变量别名化为lambda表达式,从而导致以下错误:

NHibernate.QueryException: could not resolve property: profile of: CustomerProfile.Domain.CustomerProfileAttribute

有没有办法生成一个引用局部变量的表达式?我可以使用带有Where子句的参数化表达式吗?还有其他解决方案吗?

2 个答案:

答案 0 :(得分:1)

我最终找到了答案。似乎NHibernate在其代码中以某种方式使用QueryOver表达式中的变量名称。我在工厂中更改了参数名称以匹配方法中的变量名称,并且它有效!

答案 1 :(得分:0)

QueryOver不是LINQ,因此它在接受的表达式中受到更多限制。

除非你真的需要那些左连接(我无法分辨),否则我可能会使用LINQ。它会不那么复杂。