private FromElement CreateManyToMany( string role, string associatedEntityName, string roleAlias, IEntityPersister entityPersister, EntityType type, JoinType joinType) { FromElement elem; SessionFactoryHelperExtensions sfh = _fromClause.SessionFactoryHelper; if (_inElementsFunction /*implied*/) { // For implied many-to-many, just add the end join. JoinSequence joinSequence = CreateJoinSequence(roleAlias, joinType); elem = CreateJoin(associatedEntityName, roleAlias, joinSequence, type, true); } else { // For an explicit many-to-many relationship, add a second join from the intermediate // (many-to-many) table to the destination table. Also, make sure that the from element's // idea of the destination is the destination table. string tableAlias = _fromClause.AliasGenerator.CreateName(entityPersister.EntityName); string[] secondJoinColumns = sfh.GetCollectionElementColumns(role, roleAlias); // Add the second join, the one that ends in the destination table. JoinSequence joinSequence = CreateJoinSequence(roleAlias, joinType); joinSequence.AddJoin(sfh.GetElementAssociationType(_collectionType), tableAlias, joinType, secondJoinColumns); elem = CreateJoin(associatedEntityName, tableAlias, joinSequence, type, false); elem.UseFromFragment = true; } return(elem); }
public FromElement CreateElementJoin(IQueryableCollection queryableCollection) { _implied = true; //TODO: always true for now, but not if we later decide to support elements() in the from clause _inElementsFunction = true; IType elementType = queryableCollection.ElementType; if (!elementType.IsEntityType) { throw new InvalidOperationException("Cannot create element join for a collection of non-entities!"); } _queryableCollection = queryableCollection; SessionFactoryHelperExtensions sfh = _fromClause.SessionFactoryHelper; IEntityPersister entityPersister = queryableCollection.ElementPersister; string tableAlias = _fromClause.AliasGenerator.CreateName(entityPersister.EntityName); string associatedEntityName = entityPersister.EntityName; IEntityPersister targetEntityPersister = sfh.RequireClassPersister(associatedEntityName); // Create the FROM element for the target (the elements of the collection). FromElement destination = CreateAndAddFromElement( associatedEntityName, _classAlias, targetEntityPersister, (EntityType)queryableCollection.ElementType, tableAlias ); // If the join is implied, then don't include sub-classes on the element. if (_implied) { destination.IncludeSubclasses = false; } _fromClause.AddCollectionJoinFromElementByPath(_path, destination); // origin.addDestination(destination); // Add the query spaces. _fromClause.Walker.AddQuerySpaces(entityPersister.QuerySpaces); CollectionType type = queryableCollection.CollectionType; string role = type.Role; string roleAlias = _origin.TableAlias; string[] targetColumns = sfh.GetCollectionElementColumns(role, roleAlias); IAssociationType elementAssociationType = sfh.GetElementAssociationType(type); // Create the join element under the from element. JoinSequence joinSequence = sfh.CreateJoinSequence(_implied, elementAssociationType, tableAlias, JoinType.InnerJoin, targetColumns); FromElement elem = InitializeJoin(_path, destination, joinSequence, targetColumns, _origin, false); elem.UseFromFragment = true; // The associated entity is implied, but it must be included in the FROM. elem.CollectionTableAlias = roleAlias; // The collection alias is the role. return(elem); }