private void ProcessManyToManyReference( Entity entity, DirectedReference directedReference, Action<object> addItem, Dictionary<ITable, int> manyToManySameTableProcessingCounts, string collectionCascade, string lazy, string orderByClause, bool inverse) { if (directedReference.FromEndEnabled == false) return; ITable referenceMappedTable = directedReference.Reference.MappedTable(); ITable fromPrimaryMappedTable = EntityMapper.GetPrimaryTable(entity); ITable toPrimaryMappedTable = EntityMapper.GetPrimaryTable(directedReference.ToEntity); Cardinality cardinalityPrimary; Cardinality cardinalityForeign; IKey mainKey; IKey associationKey; ITable associationTable = entity.GetAssociationTable(directedReference.ToEntity, out cardinalityPrimary, out cardinalityForeign, out mainKey, out associationKey); key keyNode = new key(); List<IColumn> fromInPrimaryKey = new List<IColumn>(); List<IColumn> toInPrimaryKey = new List<IColumn>(); if (fromPrimaryMappedTable == toPrimaryMappedTable) { // This many-to-many relationship is to the same table if (manyToManySameTableProcessingCounts.ContainsKey(toPrimaryMappedTable)) { int index = manyToManySameTableProcessingCounts[toPrimaryMappedTable]; index++; fromInPrimaryKey.AddRange(referenceMappedTable.Relationships.Where(t => t.PrimaryTable == fromPrimaryMappedTable).ElementAt(index).PrimaryKey.Columns); toInPrimaryKey.AddRange(referenceMappedTable.Relationships.Where(t => t.PrimaryTable == toPrimaryMappedTable).ElementAt(index).ForeignKey.Columns); manyToManySameTableProcessingCounts[toPrimaryMappedTable] = index; } else { fromInPrimaryKey.AddRange(referenceMappedTable.Relationships.Where(t => t.PrimaryTable == fromPrimaryMappedTable).ElementAt(0).PrimaryKey.Columns); toInPrimaryKey.AddRange(referenceMappedTable.Relationships.Where(t => t.PrimaryTable == toPrimaryMappedTable).ElementAt(0).ForeignKey.Columns); manyToManySameTableProcessingCounts.Add(toPrimaryMappedTable, 0); } } else { foreach (var coll in referenceMappedTable.Relationships.Where(t => t.PrimaryTable == fromPrimaryMappedTable).Select(r => r.ForeignKey.Columns)) foreach (var c in coll) fromInPrimaryKey.Add(c); foreach (var coll in referenceMappedTable.Relationships.Where(t => t.PrimaryTable == toPrimaryMappedTable).Select(r => r.ForeignKey.Columns)) foreach (var c in coll) toInPrimaryKey.Add(c); } if (fromInPrimaryKey.Count() == 1) keyNode.column1 = fromInPrimaryKey.First().Name.BackTick(); else foreach (var columnNode in GetColumnNodes(fromInPrimaryKey)) keyNode.AddColumn(columnNode); manytomany manyToManyNode = new manytomany(); manyToManyNode.@class = directedReference.ToEntity.Name; if (toInPrimaryKey.Count() == 1) manyToManyNode.column = toInPrimaryKey.First().Name.BackTick(); else foreach (var columnNode in GetColumnNodes(toInPrimaryKey)) keyNode.AddColumn(columnNode); collectionFetchMode collFetchMode; if (directedReference.Entity1IsFromEnd) collFetchMode = (collectionFetchMode)Enum.Parse(typeof(collectionFetchMode), directedReference.Reference.GetReferenceEnd1CollectionFetchMode().ToString(), true); else collFetchMode = (collectionFetchMode)Enum.Parse(typeof(collectionFetchMode), directedReference.Reference.GetReferenceEnd2CollectionFetchMode().ToString(), true); AssociationType type = NHCollections.GetAssociationType(directedReference); switch (type) { case AssociationType.None: Log.WarnFormat("No association type was set on reference {0} for the end {1}. This is usually an error.", directedReference.Reference.Name, directedReference.Entity1IsFromEnd ? "One" : "Two"); return; case AssociationType.Set: set setNode = CreateSetNode(directedReference, keyNode, collectionCascade, collFetchMode, lazy, inverse); setNode.table = referenceMappedTable.Name.BackTick(); setNode.Item = manyToManyNode; if (orderByClause.Length > 0) setNode.orderby = orderByClause; addItem(setNode); break; case AssociationType.Bag: bag bagNode = CreateBagNode(directedReference, keyNode, collectionCascade, collFetchMode, lazy, inverse); bagNode.table = referenceMappedTable.Name.BackTick(); bagNode.Item = manyToManyNode; if (orderByClause.Length > 0) bagNode.orderby = orderByClause; addItem(bagNode); break; case AssociationType.Map: map mapNode = CreateMapNode(directedReference, keyNode, collectionCascade, collFetchMode, lazy, inverse); mapNode.table = referenceMappedTable.Name.BackTick(); mapNode.Item = new index { column1 = NHCollections.GetIndexColumnName(directedReference), type = NHCollections.GetIndexColumnTypeName(directedReference, toPrimaryMappedTable /*fromPrimaryMappedTable*/) }; mapNode.Item1 = manyToManyNode; if (orderByClause.Length > 0) mapNode.orderby = orderByClause; addItem(mapNode); break; case AssociationType.List: list listNode = CreateListNode(directedReference, keyNode, collectionCascade, collFetchMode, lazy, inverse); listNode.table = referenceMappedTable.Name.BackTick(); listNode.Item = new index { column1 = NHCollections.GetIndexColumnName(directedReference), }; listNode.Item1 = manyToManyNode; if (orderByClause.Length > 0) listNode.orderby = orderByClause; addItem(listNode); break; // case AssociationType.IDBag: // throw new NotImplementedException( // string.Format("Have not implemented {0} association type for Many To Many relationships", type)); default: throw new NotImplementedException("AssociationType not handled yet: " + type.ToString()); } }
private void ProcessCollection( @class hClass, key keyNode, index indexNode, manytomany many, string className, string schema, string tableName, string propertyName, string cascade, AssociationType associationType, string whereClause, collectionFetchMode fetchMode, bool inverse, collectionLazy lazy, string orderByClause) { #region OrderBy string orderByPropertyName = ""; bool orderByIsAsc = true; if (!string.IsNullOrWhiteSpace(orderByClause)) { orderByClause = orderByClause.Trim(); if (orderByClause.EndsWith(" desc", StringComparison.InvariantCultureIgnoreCase)) { orderByIsAsc = false; orderByPropertyName = orderByClause.Substring(0, orderByClause.LastIndexOf(" desc", StringComparison.InvariantCultureIgnoreCase)).Trim(); } else if (orderByClause.EndsWith(" asc", StringComparison.InvariantCultureIgnoreCase)) { orderByIsAsc = false; orderByPropertyName = orderByClause.Substring(0, orderByClause.LastIndexOf(" asc", StringComparison.InvariantCultureIgnoreCase)).Trim(); } else orderByPropertyName = orderByClause; } #endregion string indexName = null; if (indexNode != null) { if (indexNode.column != null && indexNode.column.Count() > 0) indexName = indexNode.column[0].name; else indexName = indexNode.column1; } if (many != null) { var fkColumns = GetColumnNames(many.column, many.Columns()).ToList(); string thisEntityName; string otherEntityName; EntityLoader.IsNameFullyQualified(hClass.name, out thisEntityName); EntityLoader.IsNameFullyQualified(many.@class, out otherEntityName); var collectionInfo = new AssociationInformation { PropertyName = propertyName, ForeignKeyColumnNames = fkColumns, ForeignKeyBelongsToThisTable = !ForeignKeyBelongsToThisTable(hClass, fkColumns), AssociationTableName = new AssociationInformation.TableNameType(schema, tableName), ThisEntityName = thisEntityName, OtherEntityName = otherEntityName, Cardinality = Cardinality.Many, CollectionCascade = ArchAngel.Interfaces.NHibernateEnums.Helper.GetCollectionCascadeType(cascade), CollectionLazy = ArchAngel.Interfaces.NHibernateEnums.Helper.GetCollectionLazyType(lazy.ToString()), CollectionFetchMode = (CollectionFetchModes)Enum.Parse(typeof(CollectionFetchModes), fetchMode.ToString(), true), IndexColumn = indexName, WhereClause = whereClause, AssociationType = associationType, Inverse = inverse ? ArchAngel.Interfaces.NHibernateEnums.BooleanInheritedTypes.@true : ArchAngel.Interfaces.NHibernateEnums.BooleanInheritedTypes.@false, OrderByColumnName = orderByPropertyName, OrderByIsAsc = orderByIsAsc }; associationInformation.Add(collectionInfo); } else { var fkColumns = GetColumnNames(keyNode.column1, keyNode.Columns()).ToList(); string thisEntityName; string otherEntityName; EntityLoader.IsNameFullyQualified(hClass.name, out thisEntityName); EntityLoader.IsNameFullyQualified(className, out otherEntityName); bool topLevelInverse = ArchAngel.Interfaces.SharedData.CurrentProject.GetProjectDefaultInverse(); BooleanInheritedTypes inverseValue = inverse ? BooleanInheritedTypes.@true : BooleanInheritedTypes.@false; if ((inverseValue == BooleanInheritedTypes.@false && topLevelInverse == false) || (inverseValue == BooleanInheritedTypes.@true && topLevelInverse == true)) inverseValue = BooleanInheritedTypes.inherit_default; var collectionInfo = new AssociationInformation { PropertyName = propertyName, ForeignKeyColumnNames = fkColumns, ForeignKeyBelongsToThisTable = ForeignKeyBelongsToThisTable(hClass, fkColumns), // GFH ThisEntityName = thisEntityName, OtherEntityName = otherEntityName, Cardinality = Cardinality.Many, CollectionCascade = ArchAngel.Interfaces.NHibernateEnums.Helper.GetCollectionCascadeType(cascade), CollectionLazy = ArchAngel.Interfaces.NHibernateEnums.Helper.GetCollectionLazyType(lazy.ToString()), CollectionFetchMode = (CollectionFetchModes)Enum.Parse(typeof(CollectionFetchModes), fetchMode.ToString(), true), IndexColumn = indexName, AssociationType = associationType, Inverse = inverseValue, OrderByColumnName = orderByPropertyName, OrderByIsAsc = orderByIsAsc }; associationInformation.Add(collectionInfo); } }