private void MapDb() { ExtractTableColumnEdmMembers(); List <EntityType> tables = _metadataWorkspace .GetItems(DataSpace.OCSpace) .Select(x => x.GetPrivateFieldValue("EdmItem") as EntityType) .Where(x => x != null) .ToList(); foreach (var table in tables) { MapTable(table); } }
public static IEnumerable <EntityMetaData> GetMetaData(String EntityName) { var query = from meta in generatorContext.MetadataWorkspace.GetItems(DataSpace.CSpace) .Where(m => m.BuiltInTypeKind == BuiltInTypeKind.EntityType) from p in (meta as EntityType).Properties.Where(p => p.DeclaringType.Name.Equals(EntityName, StringComparison.OrdinalIgnoreCase)) select new EntityMetaData() { IsKey = (meta as EntityType).KeyMembers.Contains(p.Name), IsForeignKey = IsForeignKey(meta as EntityType, p.Name), ForeignEntityType = GetForeignEntityType(meta as EntityType, p.Name), ForeingEntitySet = GetEntitySetName(GetForeignEntityType(meta as EntityType, p.Name)), // EntityTypeName = p.DeclaringType.Name, PropertyName = p.Name, Nullable = p.Nullable, TypeUsageName = p.TypeUsage.EdmType.Name, DefaultValue = p.DefaultValue != null?p.DefaultValue.ToString() : null, Documentation = p.Documentation != null ? p.Documentation.LongDescription : null }; MetadataWorkspace mw = generatorContext.MetadataWorkspace; var items = mw.GetItems <EntityType>(DataSpace.CSpace).Where(i => i.Name.Equals(EntityName, StringComparison.OrdinalIgnoreCase)); IList <EntityMetaData> collectionProperties = new List <EntityMetaData>(); foreach (var item in items) { foreach (var navigationProprty in item.NavigationProperties) { if (navigationProprty.GetDependentProperties().Count() == 0) { EntityMetaData m = new EntityMetaData(); m.PropertyName = navigationProprty.Name; m.ForeignEntityType = GetEntityTypeName(navigationProprty.Name); m.ForeingEntitySet = navigationProprty.Name; m.IsKey = false; m.Nullable = true; m.TypeUsageName = navigationProprty.TypeUsage.EdmType.Name; m.Documentation = navigationProprty.Documentation != null ? navigationProprty.Documentation.LongDescription : null; m.IsCollectionEntity = true; collectionProperties.Add(m); } } } return(query.Concat <EntityMetaData>(collectionProperties)); }
private static EntityType FindObjectSpaceEntityMetadata(MetadataWorkspace metadata, EntityType entityType) { // Get the entity type from the model that maps to the CLR type var entityTypes = metadata .GetItems <EntityType>(DataSpace.OSpace) // OSpace = Object Space .Where(e => e == entityType) .ToList(); if (entityTypes.Count() != 1) { throw new EnumGeneratorException(string.Format("{0} entities of type {1} found in mapping.", entityTypes.Count(), entityType)); } var entityMetadata = entityTypes.Single(); return(entityMetadata); }
public static String ForeignKeyName(String ParentEntityName, String ChildEntityName) { MetadataWorkspace mw = generatorContext.MetadataWorkspace; var items = mw.GetItems <EntityType>(DataSpace.CSpace).Where(i => i.Name.Equals(ChildEntityName, StringComparison.OrdinalIgnoreCase)); foreach (var item in items) { foreach (var navigationProprty in item.NavigationProperties) { if (navigationProprty.GetDependentProperties().Count() != 0 && navigationProprty.Name == ParentEntityName) { return(navigationProprty.GetDependentProperties().ElementAt(0).Name); } } } return(null); }
/// <summary> /// /// </summary> /// <param name="metadataWorkspace"></param> /// <param name="entityContainer">Code first or DB first entityContainer</param> protected MapperBase(MetadataWorkspace metadataWorkspace, EntityContainer entityContainer) { MetadataWorkspace = metadataWorkspace; EntityContainer = entityContainer; var relations = MetadataWorkspace.GetItems(DataSpace.CSpace).OfType <AssociationType>(); foreach (var associationType in relations) { foreach (var referentialConstraint in associationType.ReferentialConstraints) { for (int i = 0; i < referentialConstraint.ToProperties.Count; ++i) { _fks[referentialConstraint.ToProperties[i]] = referentialConstraint.FromProperties[i]; } } } }
public string Process() { if (dbContext == null) { // ReSharper disable once NotResolvedInText throw new ArgumentNullException("dbContext"); } ReadOnlyCollection <GlobalItem> cSpace = metadata.GetItems(DataSpace.CSpace); ModelRoot modelRoot = ProcessRoot(); modelRoot.Classes.AddRange(cSpace.OfType <EntityType>().Select(ProcessEntity).Where(x => x != null)); modelRoot.Classes.AddRange(cSpace.OfType <ComplexType>().Select(ProcessEntity).Where(x => x != null)); modelRoot.Enumerations.AddRange(cSpace.OfType <EnumType>().Select(ProcessEnum).Where(x => x != null)); return(JsonConvert.SerializeObject(modelRoot)); }
/// <summary> /// /// </summary> /// <param name="metadataWorkspace"></param> /// <param name="entityContainer">Code first or DB first entityContainer</param> protected MapperBase(MetadataWorkspace metadataWorkspace, EntityContainer entityContainer) { MetadataWorkspace = metadataWorkspace; EntityContainer = entityContainer; var relations = MetadataWorkspace.GetItems(DataSpace.CSpace).OfType<AssociationType>(); foreach (var associationType in relations) { foreach (var referentialConstraint in associationType.ReferentialConstraints) { for (int i = 0; i < referentialConstraint.ToProperties.Count; ++i) { _fks[referentialConstraint.ToProperties[i]] = referentialConstraint.FromProperties[i]; } } } }
public static string GetForeignKeyColumnName(this MetadataWorkspace metadataWorkspace, string relationshipName) { string result = relationshipName.Split('_').Last(); var sourceEndMapping = metadataWorkspace .GetItems <EntityContainerMapping>(DataSpace.CSSpace) .Single() .AssociationSetMappings .Where(each => each.AssociationSet.Name == relationshipName) .Select(each => each.SourceEndMapping) .SingleOrDefault(); if (!ReferenceEquals(null, sourceEndMapping)) { result = sourceEndMapping .PropertyMappings .Select(each => each.Column.Name) .SingleOrDefault(); } return(result); }
public IEnumerable <T2> GetAssociationChanges <T1, T2>(T1 parent, string propertyName, EntityState findState) { ObjectContext ocontext = ((IObjectContextAdapter)this.context).ObjectContext; MetadataWorkspace metadataWorkspace = ocontext.MetadataWorkspace; // Find the AssociationType that matches the property traits given as input AssociationType atype = metadataWorkspace.GetItems <AssociationType>(DataSpace.CSpace) .Where(a => a.AssociationEndMembers.Any( ae => ae.MetadataProperties.Any(mp => mp.Name == "ClrPropertyInfo" && // Magic string!!! ((PropertyInfo)mp.Value).Name == propertyName && typeof(T1).IsAssignableFrom(((PropertyInfo)mp.Value).DeclaringType) ) ) ).First(); // Find added or deleted DbDataRecords from the above discovered type ocontext.DetectChanges(); IEnumerable <DbDataRecord> dbDataRecords = ocontext.ObjectStateManager .GetObjectStateEntries(findState) .Where(e => e.IsRelationship) // Oddly, this works, while doing the same thing below requires comparing .Name...? .Where(e => e.EntitySet.ElementType == atype) .Select(e => findState == EntityState.Deleted ? e.OriginalValues : e.CurrentValues); // Get the actual entities using the EntityKeys in the DbDataRecord IList <T2> relationChanges = new List <T2>(); foreach (System.Data.Common.DbDataRecord ddr in dbDataRecords) { EntityKey ek = (EntityKey)ddr[0]; // Comparing .ElementType to atype doesn't work, see above...? if (!(ek.GetEntitySet(metadataWorkspace).ElementType.Name == atype.Name)) { ek = (EntityKey)ddr[1]; } relationChanges.Add((T2)ocontext.GetObjectByKey(ek)); } return(relationChanges); }
/// <summary> /// 获取当前 实体数据上下文 对象中定义的所有实体集合信息。 /// </summary> /// <param name="_this">实体数据上下文 对象。</param> /// <returns>返回当前 实体数据上下文 对象中定义的所有实体集合信息。</returns> public static EntitySet[] GetEntitySets(this System.Data.Entity.DbContext _this) { Check.NotNull(_this); Type thisType = _this.GetType(); EntitySet[] sets = null; lock (_entitySetsCache) { if (!_entitySetsCache.Value.TryGetValue(thisType, out sets)) { MetadataWorkspace metadata = GetMetadataWorkspace(_this); EntityContainer container = metadata.GetItems <EntityContainer>(DataSpace.SSpace).FirstOrDefault(); if (container == null) { throw new InvalidConstraintException("获取实体数据上下文对象中的 实体容器对象失败,无法获取其 EntityContainer。"); } sets = container.EntitySets.ToArray(); _entitySetsCache.Value.Add(thisType, sets); } } return(sets); }
private static EntitySetMapping FindStorageMapping(MetadataWorkspace metadata, EntitySet conceptualEntitySet) { // Find the mapping between conceptual and storage model for this entity set var entityContainerMappings = metadata.GetItems <EntityContainerMapping>(DataSpace.CSSpace); // CSSpace = Conceptual model to Storage model mappings if (entityContainerMappings.Count() != 1) { throw new EnumGeneratorException(string.Format("{0} EntityContainerMappings found.", entityContainerMappings.Count())); } var containerMapping = entityContainerMappings.Single(); var mappings = containerMapping.EntitySetMappings.Where(s => s.EntitySet == conceptualEntitySet).ToList(); if (mappings.Count() != 1) { throw new EnumGeneratorException(string.Format( "{0} EntitySetMappings found for entitySet '{1}'.", mappings.Count(), conceptualEntitySet.Name)); } var mapping = mappings.Single(); return(mapping); }
public static IEnumerable <string> KeysFor(this DbContext context, Type entityType) { Contract.Requires(context != null); Contract.Requires(entityType != null); IEnumerable <string> keysForType; if (!KeysForTypes.TryGetValue(entityType, out keysForType)) { entityType = ObjectContext.GetObjectType(entityType); MetadataWorkspace metadataWorkspace = ((IObjectContextAdapter)context).ObjectContext.MetadataWorkspace; ObjectItemCollection objectItemCollection = (ObjectItemCollection)metadataWorkspace.GetItemCollection(DataSpace.OSpace); EntityType ospaceType = metadataWorkspace .GetItems <EntityType>(DataSpace.OSpace) .SingleOrDefault(t => objectItemCollection.GetClrType(t) == entityType); if (ospaceType == null) { throw new ArgumentException( string.Format( "The type '{0}' is not mapped as an entity type.", entityType.Name), "entityType"); } keysForType = ospaceType.KeyMembers.Select(k => k.Name); if (!KeysForTypes.Keys.Contains(entityType)) { KeysForTypes.Add(entityType, keysForType); } } return(keysForType); }
string IAuditableContext.GetForeignKeyPropertyName(Type entityType, Type parentEntityType) { EntityType type = (from meta in MetadataWorkspace.GetItems(DataSpace.CSpace) where meta.BuiltInTypeKind == BuiltInTypeKind.EntityType select meta) .OfType <EntityType>().Single(e => e.Name == parentEntityType.Name); //foreach (IRelatedEnd relatedEnd in ((IEntityWithRelationships)entityType).RelationshipManager.GetAllRelatedEnds()) //{ // foreach (IEntityWithKey relatedItem in relatedEnd) // { // object reference = null; // entities.TryGetObjectByKey(relatedItem.EntityKey, out reference); // (original as EntityObject).GetType().GetProperty(relatedEnd.TargetRoleName).SetValue(original, reference, null); // } //} //var navigationProperty = type.NavigationProperties.First(n => n.DeclaringType.Name == parentEntityType.Name); //return navigationProperty.ToEndMember.Name; throw new InvalidOperationException(string.Format("Auditing associations with Entity Framework is currently unable to automatically lookup primary and foreign keys when using this overload of AuditAssocitation(). Please use the 'AuditAssocitation<{0}>(o => o.PrimaryKey, o => o.ForeignKey)' overload to manually provide the primary and foreign keys", parentEntityType)); }
//HOW TO USE EXAMPLE: //public string GetTableName(IDbContextBase db, DbEntityEntry entry) //{ // var metadata = ((IObjectContextAdapter)db).ObjectContext.MetadataWorkspace; // return EFMetadataMappingHelper.GetTableName(metadata, entry); //} private static EntitySet getStoreSet(MetadataWorkspace metadata, EntitySetBase entitySet) { var csSpace = metadata.GetItems(DataSpace.CSSpace).Single(); var flags = BindingFlags.NonPublic | BindingFlags.Instance; var entitySetMaps = (ICollection)csSpace.GetType().GetProperty("EntitySetMaps", flags).GetValue(csSpace, null); object mapping = null; foreach (var map in entitySetMaps) { var set = map.GetType().GetProperty("Set", flags).GetValue(map, null); if (entitySet == set) { mapping = map; break; } } var m_typeMappings = ((ICollection)mapping.GetType().BaseType.GetField("m_typeMappings", flags).GetValue(mapping)).OfType <object>().Single(); var m_fragments = ((ICollection)m_typeMappings.GetType().BaseType.GetField("m_fragments", flags).GetValue(m_typeMappings)).OfType <object>().Single(); var storeSet = (EntitySet)m_fragments.GetType().GetProperty("TableSet", flags).GetValue(m_fragments, null); return(storeSet); }
// refs: // * http://romiller.com/2014/04/08/ef6-1-mapping-between-types-tables/ // * http://blogs.msdn.com/b/appfabriccat/archive/2010/10/22/metadataworkspace-reference-in-wcf-services.aspx // * http://msdn.microsoft.com/en-us/library/system.data.metadata.edm.dataspace.aspx - describes meaning of OSpace etc // * http://stackoverflow.com/questions/22999330/mapping-from-iedmentity-to-clr internal IList<EnumReference> FindEnumReferences(MetadataWorkspace metadataWorkspace) { // Get the part of the model that contains info about the actual CLR types var objectItemCollection = ((ObjectItemCollection)metadataWorkspace.GetItemCollection(DataSpace.OSpace)); // OSpace = Object Space var entities = metadataWorkspace.GetItems<EntityType>(DataSpace.OSpace); // find and return all the references to enum types var references = new List<EnumReference>(); foreach (var entityType in entities) { var mappingFragment = FindSchemaMappingFragment(metadataWorkspace, entityType); // child types in TPH don't get mappings if (mappingFragment == null) { continue; } references.AddRange(ProcessEdmProperties(entityType.Properties, mappingFragment, objectItemCollection)); } return references; }
public static IEnumerable <ReflectedForeignKeyInfo> GetForeignKeys(this MetadataWorkspace metadata, Type entityType) { var foreignKeys = metadata .GetItems <AssociationType>(DataSpace.SSpace) .SelectMany(a => a.ReferentialConstraints) .Where(rc => rc.ToRole.Name == entityType.Name) .Select(rc => { var fromEntity = metadata.GetTypeFromName(rc.ToRole.Name); var toEntity = metadata.GetTypeFromName(rc.FromRole.Name); return(new ReflectedForeignKeyInfo { FromEntity = fromEntity, FromTable = metadata.GetTableInfo(fromEntity), FromColumn = rc.ToProperties[0].Name, ToEntity = toEntity, ToTable = metadata.GetTableInfo(toEntity), ToColumn = rc.FromProperties[0].Name }); }); return(foreignKeys); }
public static string GetTableName(this MetadataWorkspace metadataWorkspace, string entityName) { string result; if (!EntityNameToTableNameOverrides.TryGetValue(entityName, out result)) { MappingFragment mappingFragment = metadataWorkspace .GetItems <EntityContainerMapping>(DataSpace.CSSpace) .Single() .EntitySetMappings .Where(each => each.EntitySet.ElementType.Name == entityName) .Select(each => each.EntityTypeMappings[0].Fragments[0]) .SingleOrDefault(); if (!ReferenceEquals(null, mappingFragment)) { result = mappingFragment.StoreEntitySet.Table; } else { result = entityName; } } return(result); }
private static EntitySetMapping FindStorageMapping(MetadataWorkspace metadata, EntitySet conceptualEntitySet) { // Find the mapping between conceptual and storage model for this entity set var entityContainerMappings = metadata.GetItems<EntityContainerMapping>(DataSpace.CSSpace); // CSSpace = Conceptual model to Storage model mappings if (entityContainerMappings.Count() != 1) { throw new EnumGeneratorException(string.Format("{0} EntityContainerMappings found.", entityContainerMappings.Count())); } var containerMapping = entityContainerMappings.Single(); var mappings = containerMapping.EntitySetMappings.Where(s => s.EntitySet == conceptualEntitySet).ToList(); if (mappings.Count() != 1) { throw new EnumGeneratorException(string.Format( "{0} EntitySetMappings found for entitySet '{1}'.", mappings.Count(), conceptualEntitySet.Name)); } var mapping = mappings.Single(); return mapping; }
private static EntityType FindObjectSpaceEntityMetadata(MetadataWorkspace metadata, EntityType entityType) { // Get the entity type from the model that maps to the CLR type var entityTypes = metadata .GetItems<EntityType>(DataSpace.OSpace) // OSpace = Object Space .Where(e => e == entityType) .ToList(); if (entityTypes.Count() != 1) { throw new EnumGeneratorException(string.Format("{0} entities of type {1} found in mapping.", entityTypes.Count(), entityType)); } var entityMetadata = entityTypes.Single(); return entityMetadata; }
private static EntitySet FindConceptualEntity(MetadataWorkspace metadata, EntityType entityType) { var entityMetadata = FindObjectSpaceEntityMetadata(metadata, entityType); // Get the entity set that uses this entity type var containers = metadata .GetItems<EntityContainer>(DataSpace.CSpace); // CSpace = Conceptual model if (containers.Count() != 1) { throw new EnumGeneratorException(string.Format("{0} EntityContainer's found.", containers.Count())); } var container = containers.Single(); var entitySets = container .EntitySets .Where(s => s.ElementType.Name == entityMetadata.Name) // doesn't seem to be possible to get at the Object-Conceptual mappings from the public API so match on name. .ToList(); // Child types in Table-per-Hierarchy don't have any mappings defined as they don't add any new tables, so skip them. if (!entitySets.Any()) { return null; } if (entitySets.Count() != 1) { throw new EnumGeneratorException(string.Format( "{0} EntitySet's found for element type '{1}'.", entitySets.Count(), entityMetadata.Name)); } var entitySet = entitySets.Single(); return entitySet; }
private Type getEntityType(EntitySetBase setBase) { Type setBaseType; if (_entityTypesCache.TryGetValue(setBase, out setBaseType)) { return(setBaseType); } // if it's an entity framework internal table then return null if (isEntityFrameworkInternalTable(setBase)) { return(null); } // Get the part of the model that contains info about the actual CLR types var objectItemCollection = ((ObjectItemCollection)_metadata.GetItemCollection(DataSpace.OSpace)); // Get conceptual model var primitiveTypeCollection = _metadata.GetItems <EntityContainer>(DataSpace.CSpace).Single(); // Get the mapping model var entityPrimitiveMappingCollection = _metadata.GetItems <EntityContainerMapping>(DataSpace.CSSpace).Single(); // Get the entity type from the model and find which entities this set base refers to var oSpace = _metadata.GetItems <EntityType>(DataSpace.OSpace); foreach (var entityType in oSpace) { // Get the entity set that uses this entity type var entitySet = primitiveTypeCollection.EntitySets .SingleOrDefault(s => s.ElementType.Name == entityType.Name); if (entitySet == null) { continue; } // Find the mapping between conceptual and storage model for this entity set var mapping = entityPrimitiveMappingCollection.EntitySetMappings .Single(s => s.EntitySet == entitySet); // Find the storage entity set (table) that the entity is mapped to. // This could be mapped to multiple entities var isRelatedTable = mapping.EntityTypeMappings .SelectMany(typeMapping => typeMapping.Fragments) .Select(fragment => fragment.StoreEntitySet) .Select(set => set.MetadataProperties) .Any(metadataCollection => (string)metadataCollection["Table"].Value == setBase.Table); // is this the table we are looking for? if (isRelatedTable) { var clrType = objectItemCollection.GetClrType(entityType); _entityTypesCache.TryAdd(setBase, clrType); return(clrType); } } // not found! return(null); }
/// <summary> /// Gets all entity sets that participate as members for the specified <paramref name="associationType"/>. /// </summary> /// <param name="workspace">Workspace with metadata.</param> /// <param name="associationType">Type of assocation to check.</param> /// <param name="member">Member of association to check.</param> /// <returns> /// All <see cref="EntitySet"/> instances that are are on the <paramref name="member"/> role for /// some association of <paramref name="associationType"/>. /// </returns> private static IEnumerable<EntitySet> GetEntitySetsWithAssociationSets( MetadataWorkspace workspace, RelationshipType associationType, RelationshipEndMember member) { Debug.Assert(workspace != null, "workspace != null"); Debug.Assert(associationType != null, "associationType != null"); Debug.Assert(member != null, "member != null"); foreach (EntityContainer container in workspace.GetItems<EntityContainer>(DataSpace.CSpace)) { foreach (AssociationSet associationSet in container.BaseEntitySets.OfType<AssociationSet>()) { if (associationSet.ElementType == associationType) { foreach (AssociationSetEnd end in associationSet.AssociationSetEnds) { if (end.CorrespondingAssociationEndMember == member) { yield return end.EntitySet; } } } } } }
/// <summary> /// /// </summary> /// <param name="context"></param> public DbMapping(DbContext context) { _context = context; _contextTypeName = context.GetType().FullName; var objectContext = ((IObjectContextAdapter)context).ObjectContext; MetadataWorkspace metadataWorkspace = objectContext.MetadataWorkspace; MapperBase mapper; EntityContainer entityContainer; if (metadataWorkspace.TryGetEntityContainer("CodeFirstDatabase", true, DataSpace.SSpace, out entityContainer)) { mapper = new CodeFirstMapper(metadataWorkspace, entityContainer); } else { ReadOnlyCollection <EntityContainer> readOnlyCollection; #if EF6 readOnlyCollection = metadataWorkspace.GetItems <EntityContainer>(DataSpace.SSpace); #else readOnlyCollection = metadataWorkspace.GetItems <EntityContainer>(DataSpace.CSpace); #endif entityContainer = readOnlyCollection[0]; mapper = new DbFirstMapper(metadataWorkspace, entityContainer); } var typeMappings = mapper.TypeMappings; int depth = 0; while (true) { if (depth > 100) { throw new Exception("Type mapping has reached unreasonable depth."); } if (typeMappings.Count == 0) { break; } var nextLevel = new Dictionary <string, EntityType>(); foreach (var kvp in typeMappings) { EntityMap entityMap; try { entityMap = mapper.MapEntity(kvp.Key, kvp.Value); } catch (ParentNotMappedYetException) { nextLevel.Add(kvp.Key, kvp.Value); continue; } if (entityMap == null) { continue; } //tableMapping.DbMapping = this; _tableMappings.Add(kvp.Key, entityMap); } typeMappings = nextLevel; depth++; } mapper.BindForeignKeys(); }
/// <summary> /// Initializes an instance of the EfMappingHelper class. /// </summary> /// <param name="db">The Entity Framework DbContext to get the mapping from.</param> public EfMappingHelper(DbContext db) { // Get a reference to the metadata workspace, from where we can retrieve information about all parts of the model. MetadataWorkspace metadata = ((IObjectContextAdapter)db).ObjectContext.MetadataWorkspace; // Conceptual part of the model has info about the shape of our entity classes. ReadOnlyCollection <EntityContainer> conceptualEntityContainers = metadata.GetItems <EntityContainer>(DataSpace.CSpace); EntityContainer conceptualContainer = conceptualEntityContainers.SingleOrDefault(); if (conceptualContainer == null) { return; } // Storage part of the model has info about the shape of our tables. ReadOnlyCollection <EntityContainer> storeContainers = metadata.GetItems <EntityContainer>(DataSpace.SSpace); EntityContainer storeContainer = storeContainers.SingleOrDefault(); if (storeContainer == null) { return; } // Object part of the model that contains info about the actual CLR types. ObjectItemCollection objectItemCollection = (ObjectItemCollection)metadata.GetItemCollection(DataSpace.OSpace); ReadOnlyCollection <EntityType> objectContainers = metadata.GetItems <EntityType>(DataSpace.OSpace); // Mapping part of model is not public, so we need to write to XML. XDocument edmx = GetEdmx(db); // Set up results. List <EfEntityMapping> entityMappings = new List <EfEntityMapping>(); List <EfRelationshipMapping> relationshipMappings = new List <EfRelationshipMapping>(); List <EfTable> tables = new List <EfTable>(); // Look through each entity in the conceptual model, and retrieve how each entity is mapped to the tables in the // storage part of the model. // // Remember that it is theoretically possible that multiple entities could be mapped to the same database table, // i.e. Table Splitting, or that one entity could be mapped to multiple database tables, i.e. "Entity Splitting". // Therefore when it comes to checking against the database, if multiple entities are mapped to the same table, // we can make sure that each of those entities have the correct data types mapped in all cases. // // Exclude the EdmMetadata table which is a table that EF may have created itself. foreach (EntitySet set in conceptualContainer.BaseEntitySets.OfType <EntitySet>().Where(e => e.Name != "EdmMetadatas")) { EfEntityMapping entityMapping = new EfEntityMapping { TableMappings = new List <EfTableMapping>() }; entityMappings.Add(entityMapping); if (objectContainers != null) { // Get the CLR type of the entity. entityMapping.EntityType = objectContainers.Select(objectItemCollection.GetClrType) .Single(e => e.Name == set.ElementType.Name); // Get the mapping fragments for this type. NOTE: Types may have multiple fragments if Entity Splitting is used. XElement element = edmx.Descendants() .SingleOrDefault(e => e.Name.LocalName == "EntityTypeMapping" && e.Attribute("TypeName")?.Value == set.ElementType.FullName); if (element != null) { IEnumerable <XElement> mappingFragments = element.Descendants() .Where(e => e.Name.LocalName == "MappingFragment"); foreach (XElement mapping in mappingFragments) { EfTableMapping tableMapping = new EfTableMapping { PropertyMappings = new List <EfPropertyMapping>() }; entityMapping.TableMappings.Add(tableMapping); // Find the table and schema that this fragment maps to. string storeSet = mapping.Attribute("StoreEntitySet")?.Value; tableMapping.TableName = (string)storeContainer .BaseEntitySets.OfType <EntitySet>() .Single(s => s.Name == storeSet) .MetadataProperties["Table"].Value; tableMapping.SchemaName = (string)storeContainer .BaseEntitySets.OfType <EntitySet>() .Single(s => s.Name == storeSet) .MetadataProperties["Schema"].Value; // Find the property-to-column mappings. IEnumerable <XElement> propertyMappings = mapping .Descendants() .Where(e => e.Name.LocalName == "ScalarProperty"); foreach (XElement propertyMapping in propertyMappings) { // Find the property and column being mapped. string propertyName = propertyMapping.Attribute("Name")?.Value ?? string.Empty; string columnName = propertyMapping.Attribute("ColumnName")?.Value ?? string.Empty; // Get the information about the property from the actual CLR class. PropertyInfo propertyInfo = entityMapping.EntityType.GetProperty(propertyName); if (propertyInfo != null) { // Get the infromation about the property from the entity model metadata. EdmProperty edmProperty = set.ElementType.Properties.Single(e => e.Name == propertyName); Facet maxLengthFacet = edmProperty.TypeUsage.Facets.SingleOrDefault(f => f.Name == "MaxLength"); int maxLength; // The only meaningful "max lengths" are from strings and binary values. // // If the property on the entity model is an enumeration, then check that the underlying type of // the enumeration is what is compared with the database. // // Use reflection to retrieve the data type defined for the property on the entity itself. PrimitiveTypeKind primitiveTypeKind = PrimitiveTypeKind.Binary; Type primitivePropertyType = null; if (edmProperty.TypeUsage.EdmType.BuiltInTypeKind == BuiltInTypeKind.EnumType) { primitiveTypeKind = edmProperty.UnderlyingPrimitiveType.PrimitiveTypeKind; // Some special handling here if there is a Nullable enumeration. If the enumeration // is nullable then the nullableEnum will be populated. Type nullableEnum = Nullable.GetUnderlyingType(propertyInfo.PropertyType); // If we're dealing with a nullable enumeration, we then have to create a nullable version of the underlying type // to compare the database schema with. Otherwise we can just call Enum.GetUnderlyingType to get the non-nullable version. primitivePropertyType = nullableEnum != null ? typeof(Nullable <>).MakeGenericType(Enum.GetUnderlyingType(nullableEnum)) : Enum.GetUnderlyingType(propertyInfo.PropertyType); } else if (edmProperty.TypeUsage.EdmType.BuiltInTypeKind == BuiltInTypeKind.PrimitiveType) { primitiveTypeKind = ((PrimitiveType)edmProperty.TypeUsage.EdmType).PrimitiveTypeKind; primitivePropertyType = propertyInfo.PropertyType; } if ((primitiveTypeKind == PrimitiveTypeKind.Binary || primitiveTypeKind == PrimitiveTypeKind.String) && maxLengthFacet != null) { // The contents of MaxLength might be the string "Max" for columns in SQL Server like // varchar(max). Therefore return -1 in these cases because this is also how SQL Server reports // the column length in its own metadata. All other values for strings with maximum lengths // should just return a numeric value. if (edmProperty.TypeUsage.Facets["MaxLength"].Value.ToString() == "Max") { maxLength = -1; } else { maxLength = (int)edmProperty.TypeUsage.Facets["MaxLength"].Value; } } else { maxLength = 0; } tableMapping.PropertyMappings.Add(new EfPropertyMapping { PropertyType = primitivePropertyType, ColumnName = columnName, IsNullable = edmProperty.Nullable, MaximumLength = maxLength }); } } } } } } // At this point, we have retrieved all of the tables that our conceptual model has mapped to, however this won't necessarily // include all of the "join" tables that are part of many-many relationships. The conceptual mapping doesn't list these tables, // therefore we have to look in the storage part of the model to actually get the list of tables that EF "knows" about. foreach (EntitySet set in storeContainer.BaseEntitySets.OfType <EntitySet>().Where(e => e.Name != "EdmMetadatas")) { EfTable table = new EfTable { TableName = set.MetadataProperties["Table"].Value.ToString(), SchemaName = set.MetadataProperties["Schema"].Value.ToString() }; tables.Add(table); } // Look through all associations configured in the "store" part of the model. These should map to the primary and foreign keys in the database. foreach (AssociationSet set in storeContainer.BaseEntitySets.OfType <AssociationSet>()) { foreach (ReferentialConstraint constraint in set.ElementType.ReferentialConstraints) { EfRelationshipMapping relationshipMapping = new EfRelationshipMapping { FromProperties = constraint.FromProperties.Select(x => x.Name).ToArray(), FromTable = storeContainer.BaseEntitySets.OfType <EntitySet>().Single(e => e.Name == constraint.FromRole.Name).Table, ToProperties = constraint.ToProperties.Select(x => x.Name).ToArray(), ToTable = storeContainer.BaseEntitySets.OfType <EntitySet>().Single(e => e.Name == constraint.ToRole.Name).Table }; relationshipMappings.Add(relationshipMapping); } } // Return results. EntityMappings = entityMappings.ToArray(); Tables = tables.ToArray(); RelationshipMappings = relationshipMappings.ToArray(); }
public ICollection <EnumLookupTable> GetEnumLookupTables() { var conceptualEntityContainer = _workspace .GetItems <EntityContainer>(DataSpace.CSpace) .Single(); var mappings = _workspace.GetItems <EntityContainerMapping>(DataSpace.CSSpace) .Single() .EntitySetMappings .ToList(); var enumSet = new Dictionary <string, EnumLookupTable>(); foreach (var conceptualEntitySet in conceptualEntityContainer.EntitySets) { var mappingFragment = mappings.Single(x => x.EntitySet == conceptualEntitySet) .EntityTypeMappings.Single() .Fragments.Single(); var tableName = mappingFragment.StoreEntitySet.Table; var tableSchema = mappingFragment.StoreEntitySet.Schema; foreach (var property in conceptualEntitySet.ElementType.Properties) { if (property.IsEnumType) { var propertyMapping = (ScalarPropertyMapping)mappingFragment.PropertyMappings .Single(x => x.Property.Name == property.Name); var reference = new TableReference { TableName = tableName, TableSchema = tableSchema, ColumnName = propertyMapping.Column.Name }; AddReference(enumSet, property.EnumType, reference); } else if (property.IsComplexType) { var complexPropertyMapping = ((ComplexPropertyMapping)mappingFragment.PropertyMappings .Single(x => x.Property.Name == property.Name)); foreach (var complexTypeProperty in property.ComplexType.Properties) { if (complexTypeProperty.IsEnumType) { var propertyMapping = (ScalarPropertyMapping)complexPropertyMapping .TypeMappings .SelectMany(x => x.PropertyMappings) .Single(x => x.Property.Name == complexTypeProperty.Name); var reference = new TableReference { TableName = tableName, TableSchema = tableSchema, ColumnName = propertyMapping.Column.Name }; AddReference(enumSet, complexTypeProperty.EnumType, reference); } } } } } return(enumSet.Values); }
private static List <Attribute> DiscoverRelatedObjectKeyAttributes(Type thisType, ObjectContext objectContext) { var attributeList = new SortedList <string, Attribute>(); //recreate foreign key column values //by adding Attributes for any key values of referenced entities //that aren't already exposed as scalar properties MetadataWorkspace mw = objectContext.MetadataWorkspace; ILookup <string, EntityType> entityTypesByName = mw.GetItems <EntityType>(DataSpace.OSpace).ToLookup(e => e.FullName); //find the EntityType metadata for T EntityType thisEntity = entityTypesByName[thisType.FullName].First(); Dictionary <string, EdmMember> thisEntityKeys = thisEntity.KeyMembers.ToDictionary(k => k.Name); //TODOx use the NavigationProperties instead of the ENtityRelations -- too complicated //TODO fix the attribute naming. Probably requires marking each attribtue as direct or related. List <PropertyInfo> erProps = thisType.GetProperties() .Where(p => typeof(EntityReference) .IsAssignableFrom(p.PropertyType)).ToList(); //For each EntityRelation property add add the keys of the related Entity foreach (PropertyInfo pi in erProps) { //Find the name of the CLR Type at the other end of the reference because we need to get its key attributes. //the property type is EntityReference<T>, we need T. string relatedEntityCLRTypeName = pi.PropertyType.GetGenericArguments().First().FullName; //Find the EntityType at the other end of the relationship because we need to get its key attributes. EntityType relatedEntityEFType = entityTypesByName[relatedEntityCLRTypeName].FirstOrDefault(); if (relatedEntityEFType == null) { throw new InvalidOperationException("Cannot find EntityType for EntityReference Property " + pi.Name); } //Add attributes for each key value of the related entity. These are the properties that //would probably appear in the storage object. The names will be the same as they are on the //related entity, except prefixed with the related entity name, //and with a check to make sure that we're not introducing a duplicate. // so if you have // if OrderItem.OrderID -> Order.ID then the column will be Order_ID // if OrderItem.OrderID -> Order.OrderID then the column will be Order_OrderID foreach (EdmMember key in relatedEntityEFType.KeyMembers) { string targetKeyAttributeName = key.Name; //TODO it would be better to get the NavigationProperty and find the ToEndMember name //but the NavigationProperty doesn't have good way to get the EntityReference //or the related entity key. string referenceName; if (pi.Name.EndsWith("Reference", StringComparison.Ordinal)) { referenceName = pi.Name.Substring(0, pi.Name.Length - "Reference".Length); } else //there's no rule that the EntityReference named like this so, if not just use the target type { referenceName = pi.PropertyType.Name; //if there are multiple relations to the same target type, just uniqify them with an index int ix = erProps.Where(p => p.PropertyType == pi.PropertyType).ToList().IndexOf(pi); if (ix > 0) { referenceName = referenceName + ix.ToString(CultureInfo.InvariantCulture); } } string fullName = referenceName + "_" + key.Name; //bind out local variables for the valueAccessor closure. Type kType = Type.GetType(key.TypeUsage.EdmType.FullName); PropertyInfo entityReferenceProperty = pi; Func <T, object> valueAccessor = o => { var er = (EntityReference) entityReferenceProperty.GetValue(o, null); //for nullable foregn keys, just return null if (er.EntityKey == null) { return(null); } object val = er.EntityKey.EntityKeyValues.First( k => k.Key == targetKeyAttributeName).Value; return(val); }; string name = key.Name; attributeList.Add(name, new Attribute(fullName, name, kType, valueAccessor, true)); } } return(attributeList.Values.ToList()); }
private static Dictionary <Type, EntitySet> CreateEntitySetMappings(MetadataWorkspace metadataWorkspace) { var entitySetMappings = new Dictionary <Type, EntitySet>(); var itemCollection = (ObjectItemCollection)metadataWorkspace.GetItemCollection(DataSpace.OSpace); var entityTypes = metadataWorkspace.GetItems <EntityType>(DataSpace.OSpace); var entityContainers = metadataWorkspace.GetItems <EntityContainer>(DataSpace.CSpace); var stack = new Stack <EntityType>(); if (entityTypes == null || entityContainers == null) { return(entitySetMappings); } foreach (EntityType type in entityTypes) { Func <EntitySetBase, bool> predicate = null; stack.Clear(); var cspaceType = (EntityType)metadataWorkspace.GetEdmSpaceType(type); do { stack.Push(cspaceType); cspaceType = (EntityType)cspaceType.BaseType; } while (cspaceType != null); EntitySet entitySet = null; while ((entitySet == null) && (stack.Count > 0)) { cspaceType = stack.Pop(); foreach (EntityContainer container in entityContainers) { if (predicate == null) { predicate = s => s.ElementType == cspaceType; } var source = container.BaseEntitySets .Where(predicate) .ToList(); int count = source.Count(); if ((count > 1) || ((count == 1) && (entitySet != null))) { throw new InvalidOperationException("Multiple entity sets per type is not supported."); } if (count == 1) { entitySet = (EntitySet)source.First(); } } } if (entitySet == null) { continue; } Type clrType = itemCollection.GetClrType(type); entitySetMappings[clrType] = entitySet; } return(entitySetMappings); }
private static Type GetClrType(MetadataWorkspace metadata, ObjectItemCollection objectItemCollection, EntityTypeBase type) { return metadata .GetItems<EntityType>(DataSpace.OSpace) .Select(objectItemCollection.GetClrType) .Single(e => e.Name == type.Name); }
private Tuple <MetadataWorkspace, SchemaData> LoadEdmx(string path) { try { string spath = Path.GetFullPath(path); XElement runtime = XElement.Load(path).Elements().First(e => e.Name.LocalName == "Runtime"); XElement csdlSchema = runtime.Elements().First(e => e.Name.LocalName == "ConceptualModels") .Elements().First(e => e.Name.LocalName == "Schema") .Elements().First(e => e.Name.LocalName == "EntityContainer") ; string entityName = csdlSchema.Attributes().First(e => e.Name.LocalName == "Name").Value; EdmItemCollection edmCollection; XElement csdl = runtime.Elements().First(e => e.Name.LocalName == "ConceptualModels") .Elements().First(e => e.Name.LocalName == "Schema"); using (XmlReader reader = csdl.CreateReader()) { edmCollection = new EdmItemCollection(new[] { reader }); } StoreItemCollection storeCollection; XElement ssdl = runtime.Elements().First(e => e.Name.LocalName == "StorageModels") .Elements().First(e => e.Name.LocalName == "Schema"); using (XmlReader reader = ssdl.CreateReader()) { storeCollection = new StoreItemCollection(new[] { reader }); } SchemaData schema = new SchemaData() { Name = entityName }; foreach (XNode nod in ssdl.Nodes()) { if (nod.NodeType == XmlNodeType.Element) { XElement nodEle = (XElement)nod; if (nodEle.Name.LocalName == "EntityType") { CodeGen.EntityType entityType = new CodeGen.EntityType() { Name = nodEle.Attribute("Name").Value }; if (entityType.Name.StartsWith("VwCustomers")) { entityType.Name = entityType.Name + ""; } List <string> primaryKeyList = new List <string>(); foreach (XNode member in ((XElement)nod).Nodes()) { if (member.NodeType == XmlNodeType.Element) { XElement nodMember = (XElement)member; if (nodMember.Name.LocalName == "Property") { Property property = new Property() { IsNullable = true }; property.Name = nodMember.Attribute("Name").Value ?? ""; property.Type = nodMember.Attribute("Type").Value ?? ""; if (nodMember.Attribute("MaxLength") != null) { property.MaxLength = int.Parse(nodMember.Attribute("MaxLength").Value); } if (nodMember.Attribute("Nullable") != null) { property.IsNullable = bool.Parse(nodMember.Attribute("Nullable").Value); } if (nodMember.Attribute("Precision") != null) { property.Precision = int.Parse(nodMember.Attribute("Precision").Value); } if (nodMember.Attribute("Scale") != null) { property.Scale = int.Parse(nodMember.Attribute("Scale").Value); } if ((nodMember.Attribute("StoreGeneratedPattern") != null) && (nodMember.Attribute("StoreGeneratedPattern").Equals("Identity"))) { property.IsIdentity = true; } entityType.Properties.Add(property.Name, property); } else if (nodMember.Name.LocalName == "Key") { foreach (XNode nodKey in ((XElement)nodMember).Nodes()) { XElement eleKey = (XElement)nodKey; string sKey = eleKey.Attribute("Name").Value ?? ""; primaryKeyList.Add(sKey); } } } } foreach (string primaryKeyName in primaryKeyList) { if (entityType.Properties.ContainsKey(primaryKeyName)) { entityType.Properties[primaryKeyName].IsKey = true; entityType.PrimaryKeys.Add(entityType.Properties[primaryKeyName]); } } schema.Add(entityType.Name, entityType); } } } StorageMappingItemCollection mappingCollection; XElement msl = runtime.Elements().First(e => e.Name.LocalName == "Mappings") .Elements().First(e => e.Name.LocalName == "Mapping"); using (XmlReader reader = msl.CreateReader()) { mappingCollection = new StorageMappingItemCollection( edmCollection, storeCollection, new[] { reader }); } MetadataWorkspace mdRet = new MetadataWorkspace(() => edmCollection, () => storeCollection, () => mappingCollection); //Resolve foriegn keys using MetadataWorkspace var relationshipEndMembers = new Dictionary <RelationshipEndMember, Tuple <System.Data.Entity.Core.Metadata.Edm.EntityType, NavigationProperty> >(); var entitySets = mdRet.GetItems <EntityContainer>(DataSpace.CSpace).First().BaseEntitySets; foreach (var s in entitySets) { try { if ((s.BuiltInTypeKind == BuiltInTypeKind.EntitySet) || (s.BuiltInTypeKind == BuiltInTypeKind.EntityType) || (s.BuiltInTypeKind == BuiltInTypeKind.EntitySetBase)) { if (s.Name.StartsWith("VwCustomers")) { var Name = (s.Name + " ").Trim(); } var navProperties = ((System.Data.Entity.Core.Metadata.Edm.EntityType)s.ElementType).DeclaredNavigationProperties; if ((navProperties.Count > 0) && (schema.ContainsKey(s.Name))) { foreach (var navProperty in navProperties) { //Thank you http://stackoverflow.com/questions/5365708/ef4-get-the-linked-column-names-from-navigationproperty-of-an-edmx AssociationType association = mdRet.GetItems <AssociationType>(DataSpace.CSpace).Single(a => a.Name == navProperty.RelationshipType.Name); string fromEntity = association.ReferentialConstraints[0].FromRole.Name; string fromEntityField = association.ReferentialConstraints[0].FromProperties[0].Name; string toEntity = association.ReferentialConstraints[0].ToRole.Name; string toEntityField = association.ReferentialConstraints[0].ToProperties[0].Name; string toEntityColumnName = toEntityField.Replace("Id", "").Replace("UID", ""); string fromEntityColumnName = fromEntityField.Replace("Id", "").Replace("UID", ""); var ns = new XmlNamespaceManager(new NameTable()); ns.AddNamespace("edmx", "http://schemas.microsoft.com/ado/2009/11/edm"); var r = entitySets.First(a => a.Name == navProperty.RelationshipType.Name); //Figure out the real entity names based off the end keys var ends = ((System.Data.Entity.Core.Metadata.Edm.AssociationSet)r).AssociationSetEnds; if (ends != null) { var fromEnd = ends.First(e => e.Name == fromEntity); if (fromEnd != null) { fromEntity = fromEnd.EntitySet.Name; } var toEnd = ends.First(e => e.Name == toEntity); if (toEnd != null) { toEntity = toEnd.EntitySet.Name; } } var newRel = new Relationship() { Name = navProperty.RelationshipType.Name, FromTableName = fromEntity, FromFieldName = fromEntityField, ToFieldName = toEntityField, ToTableName = toEntity, ToColumnName = toEntityColumnName, Type = navProperty.FromEndMember.RelationshipMultiplicity.ToString() + " to " + navProperty.ToEndMember.RelationshipMultiplicity.ToString() }; schema[s.Name].Relationships.Add(newRel); var fieldToMarkRelation = (s.Name.Equals(newRel.FromTableName) ? newRel.FromFieldName : newRel.ToFieldName); if (schema[s.Name].Properties.ContainsKey(fieldToMarkRelation)) { schema[s.Name].Properties[fieldToMarkRelation].RelatedTo.Add(newRel); } } } } } catch (Exception exE) { Console.WriteLine(exE.Message); throw; } } //Go through Edmx and get the type of object of each entity. Important because we do different things when we mess with views XElement xeele = runtime.Elements().First(e => e.Name.LocalName == "StorageModels") .Elements().First(e => e.Name.LocalName == "Schema") .Elements().First(e => e.Name.LocalName == "EntityContainer"); foreach (var item in xeele.Nodes()) { XElement ele = (XElement)item; if (ele.Attribute("Name") == null) { Console.WriteLine("Error: could not read Name Attribute"); } var name = ele.Attribute("Name").Value; var schemaName = ""; if (ele.Attribute("Schema") != null) { schemaName = ele.Attribute("Schema").Value; } XNamespace w = "http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator"; var entityType = ele.Attribute(w + "Type"); if (entityType != null) { if (schema.ContainsKey(name)) { schema[name].Type = entityType.Value.ToSingular(); schema[name].Schema = schemaName; } } } return(new Tuple <MetadataWorkspace, SchemaData>(mdRet, schema)); } catch (Exception ex) { Console.Write(ex.Message); throw; } }
private void ChangeRelationshipStates( DbContext context, EntityType entityType, object entity, EntityState state) { DebugCheck.NotNull(context); DebugCheck.NotNull(entityType); DebugCheck.NotNull(entity); var objectStateManager = ((IObjectContextAdapter)context) .ObjectContext .ObjectStateManager; var associationTypes = _metadataWorkspace .GetItems <AssociationType>(DataSpace.CSpace) .Where( at => !at.IsForeignKey && (at.SourceEnd.GetEntityType().IsAssignableFrom(entityType) || at.TargetEnd.GetEntityType().IsAssignableFrom(entityType))); foreach (var associationType in associationTypes) { if (associationType.IsManyToMany()) { continue; } AssociationEndMember principalEnd, dependentEnd; if (!associationType.TryGuessPrincipalAndDependentEnds(out principalEnd, out dependentEnd)) { principalEnd = associationType.SourceEnd; dependentEnd = associationType.TargetEnd; } if (dependentEnd.GetEntityType().IsAssignableFrom(entityType)) { var principalClrType = principalEnd.GetEntityType().GetClrType(); var set = context.Set(principalClrType); var principalStub = set.Local.Cast <object>().SingleOrDefault(); if (principalStub == null) { principalStub = set.Create(); InstantiateNullableKeys(principalStub, principalEnd.GetEntityType()); set.Attach(principalStub); } objectStateManager .ChangeRelationshipState( entity, principalStub, associationType.FullName, principalEnd.Name, state == EntityState.Deleted ? state : EntityState.Added ); } } }
private void Initialize(TContext adapter) { lock (mutex) { if (hasMetadataInitialized || adapter == null) { return; } // (1.) Create all types MetadataWorkspace workspace = adapter.ObjectContext.MetadataWorkspace; IEnumerable <EdmType> edmTypes = workspace .GetItems <EdmType>(DataSpace.CSpace) .Where(x => x.BuiltInTypeKind == BuiltInTypeKind.ComplexType || x.BuiltInTypeKind == BuiltInTypeKind.EntityType); foreach (ComplexType edmType in edmTypes.OfType <ComplexType>()) { GetCreateComplexResourceType(workspace, edmType); } foreach (EntityType edmType in edmTypes.OfType <EntityType>()) { GetCreateEntityResourceType(workspace, edmType); } // (2.) Create all entity sets string containerName = GetContainerName(adapter); IEnumerable <EntitySet> entitySets = workspace .GetEntityContainer(containerName, DataSpace.CSpace) .EntitySets; foreach (EntitySet entitySet in entitySets) { GetCreateResourceSet(workspace, entitySet); } // (3.) Create all associations IEnumerable <AssociationSet> assocSets = workspace .GetEntityContainer(GetContainerName(adapter), DataSpace.CSpace) .AssociationSets; foreach (AssociationSet assocSet in assocSets.OrderBy(x => x.Name)) { GetCreateAssociationSet(workspace, assocSet); } //foreach (AssociationSet assocSet in assocSets) // CreateConstraints(workspace, assocSet); // (4.) Create all service operations IEnumerable <MethodInfo> getOps = ReflectionHelper.GetDeclaredMethods <TService, WebGetAttribute>(); foreach (MethodInfo mi in getOps) { CreateServiceOperation(mi, "GET"); } IEnumerable <MethodInfo> postOps = ReflectionHelper.GetDeclaredMethods <TService, WebInvokeAttribute>(); foreach (MethodInfo mi in postOps) { CreateServiceOperation(mi, "POST"); } // (5.) Seal metadata types foreach (var rt in resourceTypes.Values) { rt.SetReadOnly(); } foreach (var rs in resourceSets.Values) { rs.SetReadOnly(); } foreach (var o in serviceOperations.Values) { o.SetReadOnly(); } hasMetadataInitialized = true; } }
private static void ForceViewGeneration(MetadataWorkspace workspace) { ReadOnlyCollection<EntityContainer> containers = workspace.GetItems<EntityContainer>(DataSpace.SSpace); Debug.Assert(containers.Count != 0, "no s space containers found"); Debug.Assert(containers[0].BaseEntitySets.Count != 0, "no entity sets in the sspace container"); workspace.GetCqtView(containers[0].BaseEntitySets[0]); }
/// <summary> /// Gets all <see cref="EntitySet"/> instance that may hold an entity of type <paramref name="type"/>. /// </summary> /// <param name="workspace">Workspace with metadata.</param> /// <param name="type">Entity type to get entity sets for.</param> /// <returns>An enumeration of <see cref="EntitySet"/> instances that can hold <paramref name="type"/>.</returns> private static IEnumerable<EntitySet> GetEntitySetsForType(MetadataWorkspace workspace, EntityType type) { Debug.Assert(type != null, "type != null"); Debug.Assert(workspace != null, "workspace != null"); foreach (EntityContainer container in workspace.GetItems<EntityContainer>(DataSpace.CSpace)) { foreach (EntitySet entitySet in container.BaseEntitySets.OfType<EntitySet>()) { if (IsAssignableFrom(entitySet.ElementType, type)) { yield return entitySet; } } } }
internal RelPropertyHelper(MetadataWorkspace ws, HashSet<RelProperty> interestingRelProperties) { _relPropertyMap = new Dictionary<EntityTypeBase, List<RelProperty>>(); _interestingRelProperties = interestingRelProperties; foreach (RelationshipType relationshipType in ws.GetItems<RelationshipType>(DataSpace.CSpace)) { ProcessRelationship(relationshipType); } }
private static EntityMetadataBuilder FromEntityType(this MetadataModelBuilder builder, MetadataWorkspace metadata, EntityType entityType) { var objectItemCollection = (ObjectItemCollection)metadata.GetItemCollection(DataSpace.OSpace); var mapping = metadata.GetItems <EntityContainerMapping>(DataSpace.CSSpace) .Single() .EntitySetMappings .SelectMany(p => p.EntityTypeMappings); var objectTypes = metadata.GetItems <EntityType>(DataSpace.OSpace); var objectType = objectTypes.Single(p => p.Name == entityType.Name); var clrType = objectItemCollection.GetClrType(objectType); var entityBuilder = builder.Entity(clrType); if (entityType.BaseType != null) { var baseEntityBuilder = builder.FromEntityType(metadata, (EntityType)entityType.BaseType); entityBuilder.BaseEntity = baseEntityBuilder; } var propertyMappings = mapping.SelectMany(p => p.Fragments.SelectMany(x => x.PropertyMappings)).OfType <ScalarPropertyMapping>().ToList(); var joined = from p in entityType.Properties.Where(p => p.DeclaringType == entityType) join m in propertyMappings on p equals m.Property select new { Property = p, Column = m.Column }; foreach (var prop in joined) { var propertyClrType = metadata.GetClrTypeFromCSpaceType(prop.Property); var propBuilder = entityBuilder.Property(prop.Property.Name, propertyClrType); propBuilder.Nullable = prop.Property.Nullable; if (prop.Column.IsStoreGeneratedComputed) { propBuilder.ValueGeneration = AutoGenerateValue.Both; } else if (prop.Column.IsStoreGeneratedIdentity) { propBuilder.ValueGeneration = AutoGenerateValue.OnInsert; } propBuilder.HasDefaultValue = prop.Column.MetadataProperties.Any(p => p.IsAnnotation && p.Name.EndsWith(":" + DefaultValueAnnotation.AnnotationName, StringComparison.Ordinal)); if (propBuilder is TextPropertyBuilder textBuilder) { textBuilder.MaxLength = prop.Property.MaxLength; } else if (propBuilder is BlobPropertyBuilder blobPropertyBuilder) { blobPropertyBuilder.MaxLength = prop.Property.MaxLength; } } if (entityType.BaseType == null) { foreach (var pk in entityType.KeyProperties) { entityBuilder.PrimaryKey.Add(pk.Name); } } foreach (var nav in entityType.NavigationProperties.Where(p => p.DeclaringType == entityType)) { NavigationPropertyBuilder navBuilder = null; ////var navpropMatch = from l in item.EntityMetadata.Properties.OfType<NavigationPropertyMetadata>() //// join r in item.EntityType.NavigationProperties on l.Name equals r.Name //// select new { Left = l, Right = r }; ////foreach (var npmatch in navpropMatch) ////{ //// var test = entityTypes.SelectMany(p => p.NavigationProperties) //// .FirstOrDefault(p => p.ToEndMember == npmatch.Right.FromEndMember); var inverse = nav.ToEndMember.GetEntityType().NavigationProperties.FirstOrDefault(p => p.FromEndMember == nav.ToEndMember); ////var inverse = nav.ToEndMember.MetadataProperties.FirstOrDefault(p => p.Name == "ClrPropertyInfo")?.Value as PropertyInfo; var targetObjectType = objectTypes.Single(p => p.Name == nav.ToEndMember.GetEntityType().Name); var targetClrType = objectItemCollection.GetClrType(targetObjectType); string targetPropertyName = inverse?.Name; List <string> foreignKeys = new List <string>(); var multiplicity = GetMultiplicity(nav.ToEndMember.RelationshipMultiplicity); var targetMultiplicity = GetMultiplicity(nav.FromEndMember.RelationshipMultiplicity); if (multiplicity != NavigationPropertyMultiplicity.Many) { foreignKeys.AddRange(nav.GetDependentProperties().Select(p => p.Name)); } navBuilder = entityBuilder.Navigation(nav.Name); navBuilder.Nullable = multiplicity == NavigationPropertyMultiplicity.ZeroOrOne; navBuilder.Multiplicity = multiplicity; navBuilder.Target = new ClrTypeInfo(targetClrType); navBuilder.TargetProperty = targetPropertyName; navBuilder.TargetMultiplicity = targetMultiplicity; navBuilder.ForeignKey = foreignKeys; } return(entityBuilder); }
public string Process() { if (dbContext == null) { log.Error("Process: dbContext is null"); // ReSharper disable once NotResolvedInText throw new ArgumentNullException("dbContext"); } ReadOnlyCollection <GlobalItem> oSpace = metadata.GetItems(DataSpace.OSpace); log.Debug($"Found {oSpace.Count} OSpace items"); ReadOnlyCollection <GlobalItem> sSpace = metadata.GetItems(DataSpace.SSpace); log.Debug($"Found {sSpace.Count} SSpace items"); ReadOnlyCollection <GlobalItem> cSpace = metadata.GetItems(DataSpace.CSpace); log.Debug($"Found {cSpace.Count} CSpace items"); // Context /////////////////////////////////////////// ModelRoot modelRoot = ProcessRoot(); // Entities /////////////////////////////////////////// List <ModelClass> modelClasses = oSpace.OfType <EntityType>() .Select(e => ProcessEntity(e.FullName , oSpace.OfType <EntityType>().SingleOrDefault(o => o.FullName == e.FullName) , sSpace?.OfType <EntityType>().SingleOrDefault(s => s.FullName == "CodeFirstDatabaseSchema." + e.FullName.Split('.').Last()) , cSpace.OfType <EntityType>().SingleOrDefault(c => c.FullName == e.FullName))) .Where(x => x != null) .ToList(); log.Debug($"Adding {modelClasses.Count} classes"); modelRoot.Classes.AddRange(modelClasses); // Complex types /////////////////////////////////////////// modelClasses = oSpace.OfType <ComplexType>() .Select(e => ProcessComplexType(e.FullName , oSpace.OfType <EntityType>().SingleOrDefault(s => s.FullName == e.FullName) , sSpace?.OfType <EntityType>().SingleOrDefault(s => s.FullName == "CodeFirstDatabaseSchema." + e.FullName.Split('.').Last()) , cSpace.OfType <EntityType>().SingleOrDefault(c => c.FullName == e.FullName))) .Where(x => x != null) .ToList(); log.Debug($"Adding {modelClasses.Count} complex types"); modelRoot.Classes.AddRange(modelClasses); // Enums /////////////////////////////////////////// List <ModelEnum> modelEnums = oSpace.OfType <EnumType>().Select(ProcessEnum).Where(x => x != null).ToList(); log.Debug($"Adding {modelEnums.Count} enumerations"); modelRoot.Enumerations.AddRange(modelEnums); // Put it all together /////////////////////////////////////////// log.Debug("Serializing to JSON string"); return(JsonConvert.SerializeObject(modelRoot)); }
private static IList <Attribute> DiscoverMetadata(Type thisType, ObjectContext objectContext) { //Not a collection of entities, just an IEnumerable<String> or other scalar type. //So add just a single Attribute that returns the object itself if (IsScalarType(thisType)) { return(new[] { new Attribute("Value", thisType, t => t) }); } var attributeList = new SortedList <string, Attribute>(); //find all the scalar properties and any EF EntityReference properties var allProperties = (from p in thisType.GetProperties() where IsScalarType(p.PropertyType) || typeof(EntityReference).IsAssignableFrom(p.PropertyType) select new { PropertyInfo = p, IsEntityReference = typeof(EntityReference).IsAssignableFrom(p.PropertyType) }).ToList(); //add the normal scalar properties foreach (PropertyInfo pi in from p in allProperties where !p.IsEntityReference select p.PropertyInfo) { attributeList.Add(pi.Name, new Attribute(pi)); } //if there is no ObjectContext, then just return the scalar properties if (objectContext == null) { return(attributeList.Values); } //if there is an ObjectContext, recreate foreign key column values //by adding Attributes for any key values of referenced entities //that aren't already exposed as scalar properties MetadataWorkspace mw = objectContext.MetadataWorkspace; ILookup <string, EntityType> entityTypesByName = mw.GetItems <EntityType>(DataSpace.OSpace).ToLookup(e => e.FullName); //find the EntityType metadata for T EntityType thisEntity = entityTypesByName[thisType.FullName].First(); Dictionary <string, EdmMember> thisEntityKeys = thisEntity.KeyMembers.ToDictionary(k => k.Name); //For each EntityRelation property add add the keys of the related Entity foreach (PropertyInfo pi in from p in allProperties where p.IsEntityReference select p.PropertyInfo) { //Find the name of the CLR Type at the other end of the reference because we need to get its key attributes. //the property type is EntityReference<T>, we need T. string relatedEntityCLRTypeName = pi.PropertyType.GetGenericArguments().First().FullName; //Find the EntityType at the other end of the relationship because we need to get its key attributes. EntityType relatedEntityEFType = entityTypesByName[relatedEntityCLRTypeName].FirstOrDefault(); if (relatedEntityEFType == null) { throw new InvalidOperationException("Cannot find EntityType for EntityReference Property " + pi.Name); } //Add attributes for each key value of the related entity. These are the properties that //would probably appear in the storage object. The names will be the same as they are on the //related entity, except with a check to make sure that we're not introducing a duplicate. foreach (EdmMember key in relatedEntityEFType.KeyMembers) { string fkAttributeName = key.Name; if (thisEntityKeys.ContainsKey(fkAttributeName)) { continue; //skip these. They are already exposed as regular scalar properties. } //Now ensure that the key name doesn't collide with the name of an attribute. //Uniqify by prefixing the related Entity name, eg ID => ProductID while (attributeList.ContainsKey(fkAttributeName)) { string re = relatedEntityEFType.Name; if (re.ToUpper() == re) { //ID => PRODUCT_ID fkAttributeName = re + "_" + fkAttributeName; } else { //ID => ProductID fkAttributeName = re + fkAttributeName; } } //bind out local variables for the valueAccessor closure. Type kType = Type.GetType(key.TypeUsage.EdmType.FullName); PropertyInfo entityReferenceProperty = pi; Console.WriteLine(key.Name); Func <T, object> valueAccessor = o => { var er = (EntityReference)entityReferenceProperty.GetValue(o, null); object val = er.EntityKey.EntityKeyValues.First(k => k.Key == fkAttributeName).Value; return(val); }; attributeList.Add(fkAttributeName, new Attribute(fkAttributeName, kType, valueAccessor)); } } return(attributeList.Values); }