Rename NHibernate criteria

2019-06-14 03:21发布

问题:

I am trying to join aliases multiple times but it depends on the number of times it should do it.

Employee employeeAlias = null;
Thing thingAlias = null;
var names = string[] {"A", "B", "C", "D", "E"} // number of values could vary
for(int i = 0; i < names.Length ; i++)
{
   queryOver
       .JoinAlias(() => employeeAlias.Things, 
                  () => thingAlias,
                  JoinType.LeftOuterJoin, 
                  Restrictions.Eq(Projections.Property(() => thingAlias.Name, 
                                  names[i]));
}

However, upon execution, NHibernate throws an error saying:

NHibernate.QueryException: duplicate alias: thingAlias ---> System.ArgumentException: An item with the same key has already been added

Is there a way I can make NHibernate join an alias with a specified name so that it will not re-use the name of the variable?

Thanks guys. This has been my problem since yesterday and I can't find a proper solution.

PS:

I'm trying to do something like this:

SELECT * FROM Employee e
LEFT OUTER JOIN Thing t on e.Id = t.EmployeedId AND t.Name = "A"
LEFT OUTER JOIN Thing t on e.Id = t.EmployeedId AND t.Name = "B"

回答1:

What you are trying to achieve is impossible. Each relation (many-to-one, one-to-many) can be used exactly once.

To support this statement, please, check it here: CriteriaQueryTranslator.cs

private void CreateAssociationPathCriteriaMap()
{
    foreach (CriteriaImpl.Subcriteria crit in rootCriteria.IterateSubcriteria())
    {
        string wholeAssociationPath = GetWholeAssociationPath(crit);
        try
        {
            associationPathCriteriaMap.Add(wholeAssociationPath, crit);
        }
        catch (ArgumentException ae)
        {
            throw new QueryException("duplicate association path: "
                                    + wholeAssociationPath, ae);
        }

So, what we can see here, regardless of aliases, at the end, all associtated relations (JOINS) are added into associationPathCriteriaMap, which is IDictionary<string, ICriteria>.

That means, that there is now way how to have two same keys in play...



回答2:

I didn't tried this but I think instead of using for-loop and Restrictions.Eq, we can (not sure, but in case you didn't tried it) use Restrictions.In like-

Restrictions.In(Projections.Property(() => thingAlias.Name, names));