I have a data source that supports querying based on several identifiers. These identifiers are abstracted by an IIdentifier class that wraps the type and value for the query. In my NHibernate DAO, I have the following method.
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>();
}
I would like to extract the switch statement into a factory class, as it would be useful in several other parts of my application. I tried the following:
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();
...
However, by referencing the factory class, I am aliasing the local variable into the lambda expression, leading to the following error:
NHibernate.QueryException: could not resolve property: profile of: CustomerProfile.Domain.CustomerProfileAttribute
Is there a way to generate an expression that refers to a a local variable? Could I use a parameterized expression with that Where clause? Any other solutions?
I eventually figured out the answer. It seems as if NHibernate uses the name of the variables in the QueryOver expressions somehow in its code. I changed the parameter name in my factory to match the variable name in the method, and it worked!