How linq to nhibernate by join and split where in query

I have 3 classes: Person, Employee1, Employee2

public class Employee1 : Person
{
}

public class Employee2 : Person
{
}

      

I need to query Person_Table to join Employee1_Table or Employee_Table for a while.

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 connection request is incomplete. If dto.Type is PersonType.Employee1 or PersonType.Employee2 , A1 , A2 , ...

no effect. But for the default case, the toggle A1 , A2 , ...

effect affects the query. My place is where the conditions in 3 separate classes are many and I need to add the Where

query conditions 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 an exception if the condition is B1

true. This exception message: The specified method is not supported.

Stack trace:

   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)

      

+3


source to share


1 answer


In non-standard switching cases, you return q1 and q2 respectively. These queries are never assigned by anything related to q, which explains why the Ax conditions are not present in the final query.

Also consider the line:

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

      

As with all LINQ methods, the Join () method does not affect q or q1 in any way, but instead returns a new IQueryable. The written code ignores this return value, so the string will not affect the final request.



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

You will need to change the Join () function to return the new {x, xx} in its last parameter so that you can move the .Where () call from q1 to q and still be able to access the element 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();

      

+6


source







All Articles