Domanda

I have 3 classes : Person, Employee1 , Employee2

public class Employee1 : Person
{
}

public class Employee2 : Person
{
}

I need to a query on Person_Table that some time need to join Employee1_Table or Employee_Table.

var q = SessionInstance.Query<Person>();

if (dto.Code != null)                           // A1 Condition
     q = q.Where(x => x.Code == dto.Code);

//if(A2 Condition)
//if(A3 Condition)
//...

switch (dto.Type)
{
    case PersonType.Employee1:
         var q1 = SessionInstance.Query<Employee1>();
         q.Join(q1, x => x.Id, xx => xx.Id, (x, xx) => x);

         if (!String.IsNullOrEmpty(dto.Unit))   // B1 Condition
             q1 = q1.Where(xx => xx.Unit == dto.Unit);

         //if(B2 Condition)
         //if(B3 Condition)
         //... 

         return q1.ToList<Person>();

    case PersonType.Employee2:
         var q2 = SessionInstance.Query<Employee2>();
         q.Join(q2, x => x.Id, xx => xx.Id, (x, xx) => x);

         if (!String.IsNullOrEmpty(dto.Serial)) // C1 Condition
             q2 = q2.Where(xx => xx.Serial == dto.Serial);

         //if(C2 Condition)
         //if(C3 Condition)
         //... 

         return q2.ToList<Person>();

    default:
         return q.ToList();
}

This query for join has incomplete. If dto.Type equals by PersonType.Employee1 or PersonType.Employee2, A1 , A2 , ... does not affect. But for default case of switch A1 , A2 , ... has effect on query. My Where conditions in 3 separate classes is many and I need to add Where conditions of query separately. Why?

UPDATE :

var q = SessionInstance.Query<Person>();

if (dto.Code != null)                           // A1 Condition
     q = q.Where(x => x.Code == dto.Code);

//if(A2 Condition)
//if(A3 Condition)
//...

 var q1 = SessionInstance.Query<Employee1>();

 if (!String.IsNullOrEmpty(dto.Unit))   // B1 Condition
     q1 = q1.Where(xx => xx.Unit == dto.Unit);

 //if(B2 Condition)
 //if(B3 Condition)
 //... 

 return q.Join(q1, x => x.Id, xx => xx.Id, (x, xx) => x).ToList<Person>();

This updated query has a exception if B1 condition is true. Message of this exception is : Specified method is not supported.

Stack Trace is :

   at NHibernate.Hql.Ast.ANTLR.PolymorphicQuerySourceDetector.GetClassName(IASTNode querySource)
   at NHibernate.Hql.Ast.ANTLR.PolymorphicQuerySourceDetector.Process(IASTNode tree)
   at NHibernate.Hql.Ast.ANTLR.AstPolymorphicProcessor.Process()
   at NHibernate.Hql.Ast.ANTLR.ASTQueryTranslatorFactory.CreateQueryTranslators(IASTNode ast, String queryIdentifier, String collectionRole, Boolean shallow, IDictionary`2 filters, ISessionFactoryImplementor factory)
   at NHibernate.Hql.Ast.ANTLR.ASTQueryTranslatorFactory.CreateQueryTranslators(String queryIdentifier, IQueryExpression queryExpression, String collectionRole, Boolean shallow, IDictionary`2 filters, ISessionFactoryImplementor factory)
   at NHibernate.Engine.Query.QueryPlanCache.GetHQLQueryPlan(IQueryExpression queryExpression, Boolean shallow, IDictionary`2 enabledFilters)
   at NHibernate.Impl.AbstractSessionImpl.GetHQLQueryPlan(IQueryExpression queryExpression, Boolean shallow)
   at NHibernate.Impl.AbstractSessionImpl.CreateQuery(IQueryExpression queryExpression)
   at NHibernate.Linq.NhQueryProvider.PrepareQuery(Expression expression, IQuery& query, NhLinqExpression& nhQuery)
   at NHibernate.Linq.NhQueryProvider.Execute[TResult](Expression expression)
   at Remotion.Data.Linq.QueryableBase`1.GetEnumerator()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
È stato utile?

Soluzione

In the non-default switch cases, you return q1 and q2, respectively. These queries are never assigned with anything that involves q, which explains why the Ax conditions aren't present in the final query.

Also, consider the row:

q.Join(q1, x => x.Id, xx => xx.Id, (x, xx) => x);

As with all LINQ methods, the Join method() will not affect q or q1 in any way, but instead return a new IQueryable. The code as written ignores this return value, so the line will have no effect on the final query.

You have the correct pattern everywhere else, that is: "q = q.Something....".

You will have to change the Join() to return new {x, xx} in its last parameter, so that you can move the .Where() call from q1 to q, and still have access to the item from q1. Something like:

var qJoined = q.Join(SessionInstance.Query<Employee1>(),
                     x => x.Id, xx => xx.Id,
                     (x, xx) => new {x, xx});

if (!String.IsNullOrEmpty(dto.Unit))   // B1 Condition
    qJoined = qJoined.Where(w => w.xx.Unit == dto.Unit);

return qJoined.Select(w => w.x).ToList();
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top