private MetaNavProperty CreateNavProperty(INavigation p) { var np = new MetaNavProperty(); np.NameOnServer = p.Name; np.EntityTypeName = NormalizeTypeName(p.GetTargetType().ClrType); np.IsScalar = !p.IsCollection(); // FK_<dependent type name>_<principal type name>_<foreign key property name> np.AssociationName = BuildAssocName(p); if (p.IsDependentToPrincipal()) { np.AssociationName = BuildAssocName(p); np.ForeignKeyNamesOnServer = p.ForeignKey.Properties.Select(fkp => fkp.Name).ToList(); } else { var invP = p.FindInverse(); string assocName; if (invP == null) { assocName = "Inv_" + BuildAssocName(p); } else { assocName = BuildAssocName(invP); } np.AssociationName = assocName; np.InvForeignKeyNamesOnServer = p.ForeignKey.Properties.Select(fkp => fkp.Name).ToList(); } return(np); }
private BreezeMetadata GetMetadataFromContext(DbContext dbContext) { var metadata = new BreezeMetadata(); metadata.StructuralTypes = dbContext.Model.GetEntityTypes().Select(et => { var mt = new MetaType(); metadata.StructuralTypes.Add(mt); mt.ShortName = et.Name; mt.Namespace = et.ClrType.Namespace; mt.DataProperties = et.GetProperties().Select(p => { var dp = new MetaDataProperty(); dp.NameOnServer = p.Name; dp.IsNullable = p.IsNullable; dp.IsPartOfKey = p.IsPrimaryKey(); dp.MaxLength = p.GetMaxLength(); dp.DataType = p.ClrType.ToString(); dp.ConcurrencyMode = p.IsConcurrencyToken ? "None" : "Identity"; var dfa = p.GetAnnotations().Where(a => a.Name == "DefaultValue").FirstOrDefault(); if (dfa != null) { dp.DefaultValue = dfa.Value; } return(dp); }).ToList(); mt.NavigationProperties = et.GetNavigations().Select(p => { var np = new MetaNavProperty(); np.NameOnServer = p.Name; np.EntityTypeName = p.GetTargetType().Name; np.IsScalar = !p.IsCollection(); // FK_<dependent type name>_<principal type name>_<foreign key property name> np.AssociationName = BuildAssocName(p); if (p.IsDependentToPrincipal()) { np.AssociationName = BuildAssocName(p); np.ForeignKeyNamesOnServer = p.ForeignKey.Properties.Select(fkp => fkp.Name).ToList(); } else { np.AssociationName = BuildAssocName(p.FindInverse()); np.InvForeignKeyNamesOnServer = p.ForeignKey.Properties.Select(fkp => fkp.Name).ToList(); } return(np); }).ToList(); return(mt); }).ToList(); return(metadata); }
/// <summary> /// Make association property metadata for the entity. /// Also populates the ForeignKeyMap which is used for related-entity fixup in NHContext.FixupRelationships /// </summary> /// <param name="containingPersister">Entity Persister containing the property</param> /// <param name="propType">Association property</param> /// <param name="propName">Name of the property</param> /// <param name="dataProperties">Data properties already collected for the containingType. "isPartOfKey" may be added to a property.</param> /// <param name="isKey">Whether the property is part of the key</param> /// <returns></returns> private MetaNavProperty MakeAssociationProperty(AbstractEntityPersister containingPersister, IAssociationType propType, string propName, List <MetaDataProperty> dataProperties, bool isKey) { var nmap = new MetaNavProperty(); nmap.NameOnServer = propName; var relatedEntityType = GetEntityType(propType.ReturnedClass, propType.IsCollectionType); nmap.EntityTypeName = relatedEntityType.Name + ":#" + relatedEntityType.Namespace; nmap.IsScalar = !propType.IsCollectionType; // the associationName must be the same at both ends of the association. Type containingType = containingPersister.EntityMetamodel.Type; var columnNames = GetPropertyColumnNames(containingPersister, propName, propType); nmap.AssociationName = GetAssociationName(containingType.Name, relatedEntityType.Name, columnNames); List <string> fkNames = null; var joinable = propType.GetAssociatedJoinable((ISessionFactoryImplementor)this._sessionFactory); if (propType.IsCollectionType) { // inverse foreign key var collectionPersister = joinable as AbstractCollectionPersister; if (collectionPersister != null) { // many-to-many relationships do not have a direct connection on the client or in metadata var elementPersister = collectionPersister.ElementPersister as AbstractEntityPersister; if (elementPersister != null) { fkNames = GetPropertyNamesForColumns(elementPersister, columnNames); if (fkNames != null) { nmap.InvForeignKeyNamesOnServer = fkNames; } } } } else { // Not a collection type - a many-to-one or one-to-one association var entityRelationship = containingType.FullName + '.' + propName; // Look up the related foreign key name using the column name fkNames = GetPropertyNamesForColumns(containingPersister, columnNames); if (fkNames != null) { if (propType.ForeignKeyDirection == ForeignKeyDirection.ForeignKeyFromParent) { nmap.ForeignKeyNamesOnServer = fkNames; } else { nmap.InvForeignKeyNamesOnServer = fkNames; } // For many-to-one and one-to-one associations, save the relationship in ForeignKeyMap for re-establishing relationships during save _map.ForeignKeyMap.Add(entityRelationship, string.Join(",", fkNames)); if (isKey) { foreach (var fkName in fkNames) { var relatedDataProperty = FindPropertyByName(dataProperties, fkName) as MetaDataProperty; relatedDataProperty.IsPartOfKey = true; } } } else if (fkNames == null) { nmap.ForeignKeyNamesOnServer = columnNames; //nmap.Add("ERROR", "Could not find matching fk for property " + entityRelationship); _map.ForeignKeyMap.Add(entityRelationship, string.Join(",", columnNames)); throw new ArgumentException("Could not find matching fk for property " + entityRelationship); } } return(nmap); }