/// <summary> /// Loop through all the specified properties, including the children of any complex type properties, looking for enum types. /// </summary> /// <param name="properties">The properties to search.</param> /// <param name="mappingFragment">Information needed from ef metadata to map table and its columns</param> /// <param name="objectItemCollection">For looking up ClrTypes of any enums encountered</param> /// <returns>All the references that were found in a form suitable for creating lookup tables and foreign keys</returns> private static IEnumerable<EnumReference> ProcessEdmProperties(IEnumerable<EdmProperty> properties, MappingFragment mappingFragment, ObjectItemCollection objectItemCollection) { var references = new List<EnumReference>(); // get mapped table name from mapping, or fall-back to just the name if no mapping is set, // I have no idea what causes Table to be null, and I have no unit test for it yet, but I have seen it. var table = mappingFragment.StoreEntitySet.Table ?? mappingFragment.StoreEntitySet.Name; foreach (var edmProperty in properties) { if (edmProperty.IsEnumType) { references.Add(new EnumReference { ReferencingTable = table, ReferencingField = GetColumnName(mappingFragment, edmProperty), EnumType = objectItemCollection.GetClrType(edmProperty.EnumType), }); continue; } if (edmProperty.IsComplexType) { // Note that complex types can't be nested (ref http://stackoverflow.com/a/20332503/10245 ) // so it's safe to not recurse even though the data model suggests you should have to. references.AddRange( from nestedProperty in edmProperty.ComplexType.Properties where nestedProperty.IsEnumType select new EnumReference { ReferencingTable = table, ReferencingField = GetColumnName(mappingFragment, edmProperty, nestedProperty), EnumType = objectItemCollection.GetClrType(nestedProperty.EnumType), }); } } return references; }
private static string GetTableName(Type type, DbContext context) { MetadataWorkspace metadata = ((IObjectContextAdapter)context).ObjectContext.MetadataWorkspace; // Get the part of the model that contains info about the actual CLR types ObjectItemCollection objectItemCollection = (ObjectItemCollection)metadata.GetItemCollection(DataSpace.OSpace); // Get the entity type from the model that maps to the CLR type EntityType entityType = metadata .GetItems <EntityType>(DataSpace.OSpace) .FirstOrDefault(e => objectItemCollection.GetClrType(e) == type); if (entityType == null) { return(null); } // Get the entity set that uses this entity type EntitySet entitySet = metadata .GetItems <EntityContainer>(DataSpace.CSpace) .Single() .EntitySets .FirstOrDefault(s => s.ElementType.Name == entityType.Name); if (entitySet == null) { return(null); } // Find the mapping between conceptual and storage model for this entity set EntitySetMapping mapping = metadata.GetItems <EntityContainerMapping>(DataSpace.CSSpace) .Single() .EntitySetMappings .Single(s => s.EntitySet == entitySet); if (mapping == null) { return(null); } // Find the storage entity set (table) that the entity is mapped EntitySet table = mapping .EntityTypeMappings.Single() .Fragments.Single() .StoreEntitySet; // Return the table name from the storage entity set return(string.Format("[{0}].[{1}]", table.Schema, (string)table.MetadataProperties["Table"].Value ?? table.Name)); }
public static IQueryable GetQuery( this ObjectContext oc, string entitySetName) { EntitySet entitySet = oc.MetadataWorkspace .GetEntityContainer(oc.DefaultContainerName, DataSpace.CSpace) .EntitySets[entitySetName]; EntityType entityType = oc.MetadataWorkspace.GetItem <EntityType>( entitySet.ElementType.FullName, DataSpace.OSpace); ObjectItemCollection objectItems = oc.MetadataWorkspace.GetItemCollection(DataSpace.OSpace) as ObjectItemCollection; Type clrType = objectItems.GetClrType(entityType); return(GetQuery(oc, clrType, entitySetName)); }
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); }
/// <summary> /// Gets a dictionary of all entity types associated with the current DbContext type. /// The key is the EntityType (CSpace) and the value is the CLR type of the generated entity. /// </summary> /// <returns>A dictionary keyed by entity type and returning corresponding CLR type</returns> private Dictionary <EntityType, Type> GetEntityTypesInContext() { Dictionary <EntityType, Type> entities = new Dictionary <EntityType, Type>(); ObjectItemCollection itemCollection = this.MetadataWorkspace.GetItemCollection(DataSpace.OSpace) as ObjectItemCollection; foreach (EntityType objectSpaceEntityType in itemCollection.GetItems <EntityType>()) { Type clrType = itemCollection.GetClrType(objectSpaceEntityType); // Skip the EF CodeFirst specific EdmMetadata type if (DbContextUtilities.CompareWithSystemType(clrType, BusinessLogicClassConstants.EdmMetadataTypeName)) { continue; } StructuralType edmEntityType; if (this.MetadataWorkspace.TryGetEdmSpaceType(objectSpaceEntityType, out edmEntityType)) { entities[(EntityType)edmEntityType] = clrType; } } return(entities); }
private static EntitySet GetTable(Type type, DbContext context) { EntitySet table = null; MetadataWorkspace metadata = ((IObjectContextAdapter)context).ObjectContext.MetadataWorkspace; // Get the part of the model that contains info about the actual CLR types ObjectItemCollection objectItemCollection = (ObjectItemCollection)metadata.GetItemCollection(DataSpace.OSpace); // Get the entity type from the model that maps to the CLR type EntityType entityType = metadata.GetItems <EntityType>(DataSpace.OSpace) .SingleOrDefault(e => objectItemCollection.GetClrType(e) == type); if (entityType != null) { // Get the entity set that uses this entity type EntitySet entitySet = metadata.GetItems <EntityContainer>(DataSpace.CSpace) .SingleOrDefault() ?.EntitySets ?.SingleOrDefault(s => s.ElementType.Name == entityType.Name); if (entitySet != null) { // Find the mapping between conceptual and storage model for this entity set EntitySetMapping mapping = metadata.GetItems <EntityContainerMapping>(DataSpace.CSSpace) .SingleOrDefault() ?.EntitySetMappings ?.SingleOrDefault(s => s.EntitySet == entitySet); // Find the storage entity set (table) that the entity is mapped table = mapping?.EntityTypeMappings?.SelectMany(m => m.Fragments.Select(f => f.StoreEntitySet))?.Distinct().FirstOrDefault(); //table = mapping?.EntityTypeMappings.SingleOrDefault()?.Fragments?.SingleOrDefault()?.StoreEntitySet; } } return(table); }
public virtual Type GetClrType(StructuralType item) { return(_objectItemCollection.GetClrType(item)); }
public static AssociationType ForeignKeyForNavigationProperty(this DbContext context, Type type, PropertyInfo navigationProperty) { MetadataWorkspace metadata = ((IObjectContextAdapter)context).ObjectContext.MetadataWorkspace; ObjectItemCollection objectItemCollection = metadata.GetItemCollection(DataSpace.OSpace) as ObjectItemCollection; EntityType entityType = metadata.GetItems <EntityType>(DataSpace.OSpace).SingleOrDefault(e => objectItemCollection.GetClrType(e) == GetBaseTypeFor(type)); EntitySet entitySet = metadata.GetItems <EntityContainer>(DataSpace.CSpace).Single().EntitySets.Single(s => s.ElementType.Name == entityType.Name); EntitySetMapping mapping = metadata.GetItems <EntityContainerMapping>(DataSpace.CSSpace).Single().EntitySetMappings.Single(s => s.EntitySet == entitySet); string entityIdentity = mapping.EntityTypeMappings.First().EntityType.ToString(); entityType = metadata.GetItem <EntityType>(entityIdentity, DataSpace.CSpace); return(entityType.NavigationProperties.Single(p => p.Name.Equals(navigationProperty.Name)).ToEndMember.DeclaringType as AssociationType); }
private bool IsComplexType(Type clrType) { MetadataWorkspace metadataWorkspace = this.GetObjectContextWithoutDatabaseInitialization().MetadataWorkspace; ObjectItemCollection objectItemCollection = (ObjectItemCollection)metadataWorkspace.GetItemCollection(DataSpace.OSpace); return(metadataWorkspace.GetItems <ComplexType>(DataSpace.OSpace).Any <ComplexType>((Func <ComplexType, bool>)(t => objectItemCollection.GetClrType((StructuralType)t) == clrType))); }
internal Type GetClrType(EnumType enumType) { var objectSpaceType = (EnumType)_context.MetadataWorkspace.GetObjectSpaceType(enumType); return(_objectSpaceItems.GetClrType(objectSpaceType)); }
/// <summary> /// Generates metadata for given item collection. /// Fetches CLR models from object item collection. /// </summary> /// <param name="metadataWorkspace">The metadata workspace.</param> /// <param name="itemCollection">The item collection.</param> /// <param name="objectItemCollection">The object item collection.</param> /// <param name="assembly">The assembly.</param> /// <param name="connectionString">The connection string.</param> /// <returns></returns> /// <exception cref="BeetleException">Cannot load mapping information.</exception> public static Metadata Generate(MetadataWorkspace metadataWorkspace, ItemCollection itemCollection, ObjectItemCollection objectItemCollection, Assembly assembly, string connectionString) { XDocument mappingXml = null; XNamespace mappingNs = null; try { var csResourceMatch = Regex.Match(connectionString, @"res:*/(.*?\.msl)"); if (csResourceMatch.Success) { var csResourceIndex = csResourceMatch.Value.LastIndexOf('/'); if (csResourceIndex >= 0) { var csResource = csResourceMatch.Value.Substring(csResourceIndex + 1); if (!string.IsNullOrEmpty(csResource)) { using (var stream = assembly.GetManifestResourceStream(csResource)) { if (stream != null) { using (var reader = new StreamReader(stream)) { mappingXml = XDocument.Load(reader); // ReSharper disable once PossibleNullReferenceException mappingNs = mappingXml.Root.GetDefaultNamespace(); } } } } } } } catch { mappingXml = null; } var container = itemCollection.OfType<EntityContainer>().FirstOrDefault(); // collect necessary entity information in one collection. var entityResources = new List<EntityResource>(); foreach (var entityType in itemCollection.OfType<EntityType>().OrderBy(et => et.Name)) { var et = entityType; var entitySet = GetEntitySet(container, et); IEnumerable<KeyValuePair<string, string>> propertyMappings = null; XElement entityMap = null; if (mappingXml != null) { entityMap = mappingXml .Descendants(mappingNs.GetName("EntitySetMapping")) .First(esm => esm.Attribute("Name").Value == entitySet.Name) .Descendants(mappingNs.GetName("EntityTypeMapping")) .First(mf => { var typeName = mf.Attribute("TypeName").Value; return typeName == et.FullName || typeName == string.Format("IsTypeOf({0})", et.FullName); }) .Descendants(mappingNs.GetName("MappingFragment")) .Single(); propertyMappings = entityMap.Descendants(mappingNs.GetName("ScalarProperty")) .Select(sp => new KeyValuePair<string, string>(sp.Attribute("Name").Value, sp.Attribute("ColumnName").Value)); } var complexProperties = et.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == et); Dictionary<EdmProperty, IEnumerable<ColumnMapping>> complexMappings = null; if (entityMap != null) { complexMappings = new Dictionary<EdmProperty, IEnumerable<ColumnMapping>>(); foreach (var complexProperty in complexProperties) { var complexMapping = entityMap .Descendants(mappingNs.GetName("ComplexProperty")) .First(cp => cp.Attribute("Name").Value == complexProperty.Name) .Descendants(mappingNs.GetName("ScalarProperty")) .Select(p => new ColumnMapping(p.Attribute("Name").Value, p.Attribute("ColumnName").Value)); complexMappings.Add(complexProperty, complexMapping); } } var entityResource = new EntityResource { Entity = et, Type = et, Name = et.Name, EntitySet = entitySet, SimpleProperties = et.Properties .Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == et) .ToDictionary(p => propertyMappings == null ? p.Name : propertyMappings.First(pm => pm.Key == p.Name).Value, p => p), NavigationProperties = et.NavigationProperties.Where(np => np.DeclaringType == et), ComplexProperties = complexMappings, ClrType = objectItemCollection.GetClrType(objectItemCollection.OfType<EntityType>().First(x => x.Name == et.Name)), TableName = entityMap == null ? et.Name : entityMap.Attribute("StoreEntitySet").Value }; entityResources.Add(entityResource); } foreach (var complexType in itemCollection.OfType<ComplexType>().OrderBy(i => i.Name)) { var ct = complexType; var simpleProperties = ct.Properties .Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == ct) .ToDictionary(p => p.Name, p => p); var entityResource = new EntityResource { Type = ct, Name = ct.Name, SimpleProperties = simpleProperties, ClrType = objectItemCollection.GetClrType(objectItemCollection.OfType<ComplexType>().First(x => x.Name == ct.Name)) }; entityResources.Add(entityResource); } var enumResources = new List<EnumResource>(); foreach (var enumType in itemCollection.OfType<EnumType>()) { var oSpaceEnumType = objectItemCollection.OfType<EnumType>().First(x => x.Name == enumType.Name); var enumClrType = objectItemCollection.GetClrType(oSpaceEnumType); enumResources.Add(new EnumResource { EnumType = enumType, ClrType = enumClrType }); } return Mapping(entityResources, enumResources, itemCollection, container); }
internal static IEnumerable <ScalarPropertyMapping> GetEntityPropertyMappings <TEntity>(this DbContext dbContext) { // Get the metadata MetadataWorkspace metadata = ((IObjectContextAdapter)dbContext).ObjectContext.MetadataWorkspace; // Get the space within the metadata which contains information about CLR types ObjectItemCollection clrSpace = ((ObjectItemCollection)metadata.GetItemCollection(DataSpace.OSpace)); // Get the entity type from the metadata that maps to the CLR type EntityType entityEntityType = metadata.GetItems <EntityType>(DataSpace.OSpace).Single(e => clrSpace.GetClrType(e) == typeof(TEntity)); // Get the entity set that uses this entity type EntitySet entityEntitySet = metadata.GetItems <EntityContainer>(DataSpace.CSpace).Single().EntitySets.Single(s => s.ElementType.Name == entityEntityType.Name); // Get the mapping between conceptual and storage model for this entity set EntitySetMapping entityEntitySetMapping = metadata.GetItems <EntityContainerMapping>(DataSpace.CSSpace).Single().EntitySetMappings.Single(m => m.EntitySet == entityEntitySet); // Get the entity columns return(entityEntitySetMapping.EntityTypeMappings.Single().Fragments.Single().PropertyMappings.OfType <ScalarPropertyMapping>()); }
/// <summary> /// Loop through all the specified properties, including the children of any complex type properties, looking for enum types. /// </summary> /// <param name="properties">The properties to search.</param> /// <param name="mappingFragment">Information needed from ef metadata to map table and its columns</param> /// <param name="objectItemCollection">For looking up ClrTypes of any enums encountered</param> /// <returns>All the references that were found in a form suitable for creating lookup tables and foreign keys</returns> private static IEnumerable <EnumReference> ProcessEdmProperties(IEnumerable <EdmProperty> properties, MappingFragment mappingFragment, ObjectItemCollection objectItemCollection) { var references = new List <EnumReference>(); // get mapped table name from mapping, or fall-back to just the name if no mapping is set, // I have no idea what causes Table to be null, and I have no unit test for it yet, but I have seen it. var table = mappingFragment.StoreEntitySet.Table ?? mappingFragment.StoreEntitySet.Name; foreach (var edmProperty in properties) { if (edmProperty.IsEnumType) { var propertyMapping = GetPropertyMapping(mappingFragment.PropertyMappings, edmProperty); var propertyColumnName = GetColumnNameFromPropertyMapping(edmProperty, propertyMapping); references.Add(new EnumReference { ReferencingTable = table, ReferencingField = propertyColumnName, EnumType = objectItemCollection.GetClrType(edmProperty.EnumType), }); continue; } if (edmProperty.IsComplexType) { // Use a queue to be able to process nested complex properties // A kvp is stored where key item is the complex property and the value item is property mapping for that complex property Queue <KeyValuePair <EdmProperty, ComplexPropertyMapping> > complexPropertyQueue = new Queue <KeyValuePair <EdmProperty, ComplexPropertyMapping> >(); complexPropertyQueue.Enqueue(new KeyValuePair <EdmProperty, ComplexPropertyMapping>( edmProperty, GetComplexPropertyMapping(mappingFragment.PropertyMappings, edmProperty) )); do { //this loop adds references to enum properties from within the complex type and also //processes nested complex properties recursively by utilizing the queue. //the search is done in BFS fashion var complexPropAndContainingProperties = complexPropertyQueue.Dequeue(); var prop = complexPropAndContainingProperties.Key; var propertyMapping = complexPropAndContainingProperties.Value; references.AddRange( (from nestedProperty in prop.ComplexType.Properties where nestedProperty.IsEnumType select new EnumReference { ReferencingTable = table, ReferencingField = GetColumnNameForEnumWithinComplexProperty(propertyMapping, prop, nestedProperty), EnumType = objectItemCollection.GetClrType(nestedProperty.EnumType), }).ToArray()); var subPropertyMappings = propertyMapping .TypeMappings .Single(p => p.ComplexType.Name == prop.ComplexType.Name) .PropertyMappings; foreach (var nestedComplex in prop.ComplexType.Properties.Where(p => p.IsComplexType)) { complexPropertyQueue.Enqueue(new KeyValuePair <EdmProperty, ComplexPropertyMapping>( nestedComplex, GetComplexPropertyMapping(subPropertyMappings, nestedComplex) )); } } while (complexPropertyQueue.Any()); } } return(references); }
public static List <NavigationProperty> GetNavigationProperties <T>(this DbEntityEntry <T> entity, DbContext context) where T : class { List <System.Reflection.PropertyInfo> properties = new List <System.Reflection.PropertyInfo>(); //Get the entity type Type entityType = entity.GetType(); //Get the System.Data.Entity.Core.Metadata.Edm.EntityType //associated with the entity. MetadataWorkspace workspace = ((IObjectContextAdapter)context).ObjectContext.MetadataWorkspace; ObjectItemCollection itemCollection = (ObjectItemCollection)(workspace.GetItemCollection(DataSpace.OSpace)); EntityType etype = itemCollection.OfType <EntityType>().Single(e => itemCollection.GetClrType(e) == typeof(T)); return(etype.NavigationProperties.ToList()); }
public static Metadata Generate(MetadataWorkspace metadataWorkspace, ItemCollection itemCollection, ObjectItemCollection objectItemCollection, Assembly assembly, string modelName = null) { var container = itemCollection.OfType <EntityContainer>().First(); XDocument mappingXml = null; XNamespace mappingNs = null; try { if (modelName == null) { var schemaSource = container.MetadataProperties["SchemaSource"].Value.ToString(); modelName = Regex.Match(schemaSource, @"res://.*/(.*?)\.csdl").Groups[1].Value; } using (var stream = assembly.GetManifestResourceStream(modelName + ".msl")) { if (stream != null) { using (var reader = new StreamReader(stream)) { mappingXml = XDocument.Load(reader); // ReSharper disable once PossibleNullReferenceException mappingNs = mappingXml.Root.GetDefaultNamespace(); } } } } catch { mappingXml = null; } // collect necessary entity information in one collection. var entityResources = new List <EntityResource>(); foreach (var entityType in itemCollection.OfType <EFEntityType>().OrderBy(et => et.Name)) { var et = entityType; var entitySet = GetEntitySet(container, et); IEnumerable <KeyValuePair <string, string> > propertyMappings = null; XElement entityMap = null; if (mappingXml != null) { entityMap = mappingXml .Descendants(mappingNs.GetName("EntitySetMapping")) .First(esm => esm.Attribute("Name")?.Value == entitySet.Name) .Descendants(mappingNs.GetName("EntityTypeMapping")) .First(mf => { var typeName = mf.Attribute("TypeName")?.Value; return(typeName == et.FullName || typeName == $"IsTypeOf({et.FullName})"); }) .Descendants(mappingNs.GetName("MappingFragment")) .Single(); propertyMappings = entityMap.Descendants(mappingNs.GetName("ScalarProperty")) .Select(sp => new KeyValuePair <string, string>( sp.Attribute("Name")?.Value, sp.Attribute("ColumnName")?.Value) ); } var complexProperties = et.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == et); Dictionary <EdmProperty, IEnumerable <ColumnMapping> > complexMappings = null; if (entityMap != null) { complexMappings = new Dictionary <EdmProperty, IEnumerable <ColumnMapping> >(); foreach (var complexProperty in complexProperties) { var complexMapping = entityMap .Descendants(mappingNs.GetName("ComplexProperty")) .First(cp => cp.Attribute("Name")?.Value == complexProperty.Name) .Descendants(mappingNs.GetName("ScalarProperty")) .Select(p => new ColumnMapping(p.Attribute("Name")?.Value, p.Attribute("ColumnName")?.Value)); complexMappings.Add(complexProperty, complexMapping); } } var entityResource = new EntityResource { Entity = et, Type = et, Name = et.Name, EntitySet = entitySet, SimpleProperties = et.Properties .Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == et) .ToDictionary(p => propertyMappings == null ? p.Name : propertyMappings.First(pm => pm.Key == p.Name).Value, p => p), NavigationProperties = et.NavigationProperties.Where(np => np.DeclaringType == et), ComplexProperties = complexMappings, ClrType = objectItemCollection.GetClrType(objectItemCollection.OfType <EFEntityType>().First(x => x.Name == et.Name)), TableName = entityMap?.Attribute("StoreEntitySet")?.Value ?? et.Name }; entityResources.Add(entityResource); } foreach (var complexType in itemCollection.OfType <ComplexType>().OrderBy(i => i.Name)) { var ct = complexType; var simpleProperties = ct.Properties .Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == ct) .ToDictionary(p => p.Name, p => p); var entityResource = new EntityResource { Type = ct, Name = ct.Name, SimpleProperties = simpleProperties, ClrType = objectItemCollection.GetClrType(objectItemCollection.OfType <ComplexType>().First(x => x.Name == ct.Name)) }; entityResources.Add(entityResource); } var enumResources = new List <EnumResource>(); foreach (var enumType in itemCollection.OfType <EFEnumType>()) { var oSpaceEnumType = objectItemCollection.OfType <EFEnumType>().First(x => x.Name == enumType.Name); var enumClrType = objectItemCollection.GetClrType(oSpaceEnumType); enumResources.Add(new EnumResource { EnumType = enumType, ClrType = enumClrType }); } return(Mapping(entityResources, enumResources, itemCollection, container)); }