Inherited entities and "Relation at index 1 doesn't contain an entity already added to the FROM clause. Bad alias?"

Posts   
 
    
kievBug
User
Posts: 105
Joined: 09-Jan-2009
# Posted on: 23-Nov-2010 16:59:03   

Hey guys,

I've these entities:

Subject which has a field MemberOf:EntityCollection<Group>(relation is M:N) Group(inherited from Subject) which has a field Members:EntityCollection<Subject> (same M:N) Employee(inherited from Subject) which has a field Supervisor:Employee(M:1 relation)

As you can see:

Employee will also get fields and relations from the base entity Subject i.e. it should have a field MemberOf which is a collection of groups.

I'm trying to build a relation predicate bucket for this case: Employee.Supervisor.MemberOf i.e I've 3 relations added to a bucket: 0 - Employee to Employee using SupervisorId 1 - Subject to IntermediateTable using SubjectId 2 - IntermediateTable to Group using GroupId

But llblgen throws exception, when I'm doing:

Line 154:           Adapter.FetchTypedList(definition.Fields, resultData, definition.Relations,
Line 155:                                  definition.MaxNumberOfItemsToReturn ?? 0, definition.SortExpression,
Line 156:                                  definition.AllowDuplicates ?? true, definition.GroupBy, 

Can you please help me find the problem?

Here is a stacktrace:


ORMRelationException: Relation at index 1 doesn't contain an entity already added to the FROM clause. Bad alias?]
   SD.LLBLGen.Pro.ORMSupportClasses.RelationCollection.PreprocessRelations() in C:\Myprojects\VS.NET Projects\LLBLGen Pro v2.0\RuntimeLibraries 2.6 .NET 2.x\ORMSupportClasses\QueryApiElements\RelationCollection.cs:911
   SD.LLBLGen.Pro.ORMSupportClasses.RelationCollection.ToQueryTextInternal(Int32& uniqueMarker, Boolean ansiJoins, String& nonAnsiWhereClause, String nonAnsiRootTableReference, String nonAnsiFieldSuffix) in C:\Myprojects\VS.NET Projects\LLBLGen Pro v2.0\RuntimeLibraries 2.6 .NET 2.x\ORMSupportClasses\QueryApiElements\RelationCollection.cs:385
   SD.LLBLGen.Pro.ORMSupportClasses.RelationCollection.ToQueryText(Int32& uniqueMarker) in C:\Myprojects\VS.NET Projects\LLBLGen Pro v2.0\RuntimeLibraries 2.6 .NET 2.x\ORMSupportClasses\QueryApiElements\RelationCollection.cs:323
   SD.LLBLGen.Pro.DQE.SqlServer.DynamicQueryEngine.CreateSelectDQ(IEntityFieldCore[] selectList, IFieldPersistenceInfo[] fieldsPersistenceInfo, IDbConnection connectionToUse, IPredicate selectFilter, Int64 maxNumberOfItemsToReturn, ISortExpression sortClauses, IRelationCollection relationsToWalk, Boolean allowDuplicates, IGroupByCollection groupByClause, Boolean relationsSpecified, Boolean sortClausesSpecified) +2499
   SD.LLBLGen.Pro.ORMSupportClasses.DynamicQueryEngineBase.CreateSelectDQ(IEntityFieldCore[] selectList, IFieldPersistenceInfo[] fieldsPersistenceInfo, IDbConnection connectionToUse, IPredicate selectFilter, Int64 maxNumberOfItemsToReturn, ISortExpression sortClauses, IRelationCollection relationsToWalk, Boolean allowDuplicates, IGroupByCollection groupByClause) in C:\Myprojects\VS.NET Projects\LLBLGen Pro v2.0\RuntimeLibraries 2.6 .NET 2.x\ORMSupportClasses\Persistence\DynamicQueryEngineBase.cs:900
   SD.LLBLGen.Pro.DQE.SqlServer.SqlServerSpecificCreator.CreateSubQuery(IEntityFieldCore[] selectList, IFieldPersistenceInfo[] fieldPersistenceInfos, IPredicate selectFilter, Int64 maxNumberOfItemsToReturn, ISortExpression sortClauses, IRelationCollection relationsToWalk, IGroupByCollection groupByClause, Boolean allowDuplicates, Int32& uniqueMarker) +239
   SD.LLBLGen.Pro.ORMSupportClasses.DbSpecificCreatorBase.CreateSubQuery(IEntityFieldCore[] selectList, IFieldPersistenceInfo[] fieldPersistenceInfos, IPredicate selectFilter, Int64 maxNumberOfItemsToReturn, ISortExpression sortClauses, IRelationCollection relationsToWalk, IGroupByCollection groupByClause, Int32& uniqueMarker) in C:\Myprojects\VS.NET Projects\LLBLGen Pro v2.0\RuntimeLibraries 2.6 .NET 2.x\ORMSupportClasses\Persistence\DbSpecificCreatorBase.cs:547
   SD.LLBLGen.Pro.ORMSupportClasses.FieldCompareSetPredicate.ToQueryText(Int32& uniqueMarker, Boolean inHavingClause) in C:\Myprojects\VS.NET Projects\LLBLGen Pro v2.0\RuntimeLibraries 2.6 .NET 2.x\ORMSupportClasses\QueryApiElements\FieldCompareSetPredicate.cs:596
   SD.LLBLGen.Pro.ORMSupportClasses.PredicateExpression.ToQueryText(Int32& uniqueMarker, Boolean inHavingClause) in C:\Myprojects\VS.NET Projects\LLBLGen Pro v2.0\RuntimeLibraries 2.6 .NET 2.x\ORMSupportClasses\QueryApiElements\PredicateExpression.cs:224
   SD.LLBLGen.Pro.ORMSupportClasses.PredicateExpression.ToQueryText(Int32& uniqueMarker, Boolean inHavingClause) in C:\Myprojects\VS.NET Projects\LLBLGen Pro v2.0\RuntimeLibraries 2.6 .NET 2.x\ORMSupportClasses\QueryApiElements\PredicateExpression.cs:224
   SD.LLBLGen.Pro.ORMSupportClasses.PredicateExpression.ToQueryText(Int32& uniqueMarker) in C:\Myprojects\VS.NET Projects\LLBLGen Pro v2.0\RuntimeLibraries 2.6 .NET 2.x\ORMSupportClasses\QueryApiElements\PredicateExpression.cs:177
   SD.LLBLGen.Pro.DQE.SqlServer.DynamicQueryEngine.CreateSelectDQ(IEntityFieldCore[] selectList, IFieldPersistenceInfo[] fieldsPersistenceInfo, IDbConnection connectionToUse, IPredicate selectFilter, Int64 maxNumberOfItemsToReturn, ISortExpression sortClauses, IRelationCollection relationsToWalk, Boolean allowDuplicates, IGroupByCollection groupByClause, Boolean relationsSpecified, Boolean sortClausesSpecified) +2927
   SD.LLBLGen.Pro.ORMSupportClasses.DynamicQueryEngineBase.CreateSelectDQ(IEntityFieldCore[] selectList, IFieldPersistenceInfo[] fieldsPersistenceInfo, IDbConnection connectionToUse, IPredicate selectFilter, Int64 maxNumberOfItemsToReturn, ISortExpression sortClauses, IRelationCollection relationsToWalk, Boolean allowDuplicates, IGroupByCollection groupByClause) in C:\Myprojects\VS.NET Projects\LLBLGen Pro v2.0\RuntimeLibraries 2.6 .NET 2.x\ORMSupportClasses\Persistence\DynamicQueryEngineBase.cs:900
   SD.LLBLGen.Pro.DQE.SqlServer.DynamicQueryEngine.CreatePagingSelectDQ(IEntityFieldCore[] selectList, IFieldPersistenceInfo[] fieldsPersistenceInfo, IDbConnection connectionToUse, IPredicate selectFilter, Int64 maxNumberOfItemsToReturn, ISortExpression sortClauses, IRelationCollection relationsToWalk, Boolean allowDuplicates, IGroupByCollection groupByClause, Int32 pageNumber, Int32 pageSize) +230
   SD.LLBLGen.Pro.ORMSupportClasses.DynamicQueryEngineBase.CreateSelectDQ(IEntityFieldCore[] selectList, IFieldPersistenceInfo[] fieldsPersistenceInfo, IDbConnection connectionToUse, IPredicate selectFilter, Int64 maxNumberOfItemsToReturn, ISortExpression sortClauses, IRelationCollection relationsToWalk, Boolean allowDuplicates, IGroupByCollection groupByClause, Int32 pageNumber, Int32 pageSize) in C:\Myprojects\VS.NET Projects\LLBLGen Pro v2.0\RuntimeLibraries 2.6 .NET 2.x\ORMSupportClasses\Persistence\DynamicQueryEngineBase.cs:1004
   SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.CreateSelectDQ(IEntityFields2 fieldsToFetch, IFieldPersistenceInfo[] persistenceInfoObjects, IPredicateExpression filter, Int64 maxNumberOfItemsToReturn, ISortExpression sortClauses, IRelationCollection relationsToWalk, Boolean allowDuplicates, IGroupByCollection groupByClause, Int32 pageNumber, Int32 pageSize) in C:\Myprojects\VS.NET Projects\LLBLGen Pro v2.0\RuntimeLibraries 2.6 .NET 2.x\ORMSupportClasses\AdapterSpecific\DataAccessAdapterBase.cs:4154
   SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.CreateQueryFromElements(IEntityFields2 fieldCollectionToFetch, IRelationPredicateBucket filterBucket, Int32 maxNumberOfItemsToReturn, ISortExpression sortClauses, Boolean allowDuplicates, IGroupByCollection groupByClause, Int32 pageNumber, Int32 pageSize, IFieldPersistenceInfo[]& persistenceInfo, IRetrievalQuery& selectQuery) in C:\Myprojects\VS.NET Projects\LLBLGen Pro v2.0\RuntimeLibraries 2.6 .NET 2.x\ORMSupportClasses\AdapterSpecific\DataAccessAdapterBase.cs:4355
   SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.FetchTypedList(IEntityFields2 fieldCollectionToFetch, DataTable dataTableToFill, IRelationPredicateBucket filterBucket, Int32 maxNumberOfItemsToReturn, ISortExpression sortClauses, Boolean allowDuplicates, IGroupByCollection groupByClause, Int32 pageNumber, Int32 pageSize) in C:\Myprojects\VS.NET Projects\LLBLGen Pro v2.0\RuntimeLibraries 2.6 .NET 2.x\ORMSupportClasses\AdapterSpecific\DataAccessAdapterBase.cs:3017

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 23-Nov-2010 17:58:18   

Please verify whether you're using the latest v2.6 build of the runtimes and if not, please download the latest from our website (customer area). See: http://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=7717

Frans Bouma | Lead developer LLBLGen Pro
kievBug
User
Posts: 105
Joined: 09-Jan-2009
# Posted on: 23-Nov-2010 20:15:13   

You were right, I wasn't using the latest version, and I upgraded to 2.6.10.930. But it hasn't changed anything, I still have the same exception.

I use adapter templates and the latest version. I can't post a real code, but it is pretty clear what I'm doing.

Anton

kievBug
User
Posts: 105
Joined: 09-Jan-2009
# Posted on: 23-Nov-2010 20:43:19   

Here is my understanding of the problem:

Relation Collection look like:

0 - Employee.SupervisorId m:1 Employee.Id AliasStart = "" AliasEnd="a0"

1 - Subject.Id 1:n IntermediateTable.SubjectId AliasStart = "a0" AliasEnd="a2"

2 - IntermediateTable.GroupId m:1 Group.Id AliasStart = "a2" AliasEnd="a1"

And the problem is with relation 1 - because of the inheritance The End of the relation 0 is Employee (which is inherited from Subject), but the start of the relation 1 is Subject (i.e. base class of employee), but the Subject was not added to the join list, and that is why the exception is thrown.

There is a code in PreprocessRelations that performs some checks in case of inheritance, but it doesn't work in this case, because it checks the left side which is Subject and LeftOperandInheritanceInfo.EntityNamesOnHierarchyPath returns just a Subject in the list, thus the left operand Subject is not found in the relations.

Let me know if you need anything.

kievBug
User
Posts: 105
Joined: 09-Jan-2009
# Posted on: 23-Nov-2010 20:52:30   

When exception happens the list aliasesAlreadyInJoinList contains these keys: + ["SysSubjectEntity"] null + ["SysEmployeeEntitya0a0"] null + ["SysEmployeeEntitya0"] null + ["SysEmployeeEntity"] null + ["SysSubjectEntitya0a0"] null

and it checks for (superTypeName + currentRelation.AliasLeftOperand) "SysSubjectEntitya0"

So something is probably wrong.

MTrinder
User
Posts: 1461
Joined: 08-Oct-2008
# Posted on: 23-Nov-2010 21:17:46   

It would be useful to see the full code you are using...

Matt

kievBug
User
Posts: 105
Joined: 09-Jan-2009
# Posted on: 23-Nov-2010 21:58:41   

Well, I've created just a plain unit test for it and here is the code in the test


            var relationCollection = new RelationCollection();
            relationCollection.Add(SysEmployeeEntity.Relations.SysEmployeeEntityUsingIdSupervisorId, "", "a0", JoinHint.None);
            relationCollection.Add(SysSubjectEntity.Relations.SysGroupMembershipEntityUsingSubjectId, "a0", "a2", JoinHint.None);
            relationCollection.Add(SysGroupMembershipEntity.Relations.SysGroupEntityUsingGroupId, "a2", "a1", JoinHint.None);
            relationCollection.PreprocessRelations();

This unit-test works just fine. But if I change it a little bit:


            ...
            relationCollection.PreprocessRelations();
            relationCollection.PreprocessRelations(); // just add this line

It will fail with the same exception that I get. So probably the problem is in how I use it in application - and I'm using this relation collection in the subquery filter. I'll try to add it to the test.

kievBug
User
Posts: 105
Joined: 09-Jan-2009
# Posted on: 24-Nov-2010 01:43:47   

Ok here we go - this method is called twice for the same relation collection because at first I get a count of all records, and after that I make a query for a specific page with the same relation predicate bucket which should not be a problem at all IMHO.

So here is the code:


            int recordCount = Adapter.GetDbCount(definition.Fields, definition.Relations, definition.GroupBy,
                                                 definition.AllowDuplicates ?? true);
            var resultData = new DataTable();
            Adapter.FetchTypedList(definition.Fields, resultData, definition.Relations,
                                   definition.MaxNumberOfItemsToReturn ?? 0, definition.SortExpression,
                                   definition.AllowDuplicates ?? true, definition.GroupBy,
                                   definition.PageNumber ?? 0,
                                   definition.PageSize ?? 0);

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 24-Nov-2010 03:52:30   

Hi there,

  • You said "this method is called twice". What method?
  • So far we didn't see the full relevant code. If you want privacy you can open a Helpdesk thread which only you and support team can see.
  • Even better, if you can create a tiny repro solution (llblgen file, repro code, DDL script) which demonstrate the problem, we can offer a quicker solution to you.
David Elizondo | LLBLGen Support Team
kievBug
User
Posts: 105
Joined: 09-Jan-2009
# Posted on: 24-Nov-2010 03:58:05   

When I'm executing this test


            var relationCollection = new RelationCollection();
            relationCollection.Add(SysEmployeeEntity.Relations.SysEmployeeEntityUsingIdSupervisorId, "", "a0", JoinHint.None);
            relationCollection.Add(SysSubjectEntity.Relations.SysGroupMembershipEntityUsingSubjectId, "a0", "a2", JoinHint.None);
            relationCollection.Add(SysGroupMembershipEntity.Relations.SysGroupEntityUsingGroupId, "a2", "a1", JoinHint.None);
            relationCollection.PreprocessRelations();
            relationCollection.PreprocessRelations(); // <---- this line throws an exception

It throws an exception. And in the real code I'm doing this:


            int recordCount = Adapter.GetDbCount(definition.Fields, definition.Relations, definition.GroupBy,
                                                 definition.AllowDuplicates ?? true);
            var resultData = new DataTable();
            Adapter.FetchTypedList(definition.Fields, resultData, definition.Relations,
                                 definition.MaxNumberOfItemsToReturn ?? 0, definition.SortExpression,
                                 definition.AllowDuplicates ?? true, definition.GroupBy,
                                 definition.PageNumber ?? 0,
                                 definition.PageSize ?? 0);

As you can see relation predicate bucket is used in boths calls - to get count and to get datatable i.e. the method RelationCollection.PreprocessRelations is called twice for the same Relation Collection, the second call is throwing exception.

Walaa avatar
Walaa
Support Team
Posts: 14946
Joined: 21-Aug-2005
# Posted on: 24-Nov-2010 09:15:29   

var relationCollection = new RelationCollection(); relationCollection.Add(SysEmployeeEntity.Relations.SysEmployeeEntityUsingIdSupervisorId, "", "a0", JoinHint.None); relationCollection.Add(SysSubjectEntity.Relations.SysGroupMembershipEntityUsingSubjectId, "a0", "a2", JoinHint.None); relationCollection.Add(SysGroupMembershipEntity.Relations.SysGroupEntityUsingGroupId, "a2", "a1", JoinHint.None);

Please try the following code instead:

var relationCollection = new RelationCollection();
            relationCollection.Add(SysEmployeeEntity.Relations.SysEmployeeEntityUsingIdSupervisorId, "", "a0", JoinHint.None);
            relationCollection.Add(SysEmployeeEntity.Relations.SysGroupMembershipEntityUsingSubjectId, "a0", "a2", JoinHint.None);
            relationCollection.Add(SysGroupMembershipEntity.Relations.SysGroupEntityUsingGroupId, "a2", "a1", JoinHint.None);
kievBug
User
Posts: 105
Joined: 09-Jan-2009
# Posted on: 24-Nov-2010 17:35:35   

Ohh, right.

Thanks for your help.

Anton