Esempio n. 1
0
        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);
            }
        }
Esempio n. 2
0
        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);
        }
Esempio n. 4
0
        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];
                    }
                }
            }
        }
Esempio n. 6
0
        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));
        }
Esempio n. 7
0
        /// <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];
                    }
                }
            }
        }
Esempio n. 8
0
        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);
        }
Esempio n. 9
0
        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);
        }
Esempio n. 10
0
        /// <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);
        }
Esempio n. 13
0
        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));
        }
Esempio n. 14
0
        //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;
		}
Esempio n. 16
0
        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);
        }
Esempio n. 17
0
        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;
                     }
                 }
             }
         }
     }
 }
Esempio n. 23
0
        /// <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);
            }
Esempio n. 26
0
        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());
        }
Esempio n. 27
0
        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);
 }
Esempio n. 29
0
        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
                        );
                }
            }
        }
Esempio n. 31
0
        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);
        }
Esempio n. 36
0
        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));
        }
Esempio n. 37
0
        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);
        }