/// <summary>
 /// Constrcutor to create an instance of DefaultObjectMappingItemCollection.
 /// To start with we will create a Schema under which maps will be created.
 /// </summary>
 /// <param name="edmCollection"></param>
 /// <param name="objectCollection"></param>
 public DefaultObjectMappingItemCollection(EdmItemCollection edmCollection,
     ObjectItemCollection objectCollection) : base(DataSpace.OCSpace)
 {
     EntityUtil.CheckArgumentNull(edmCollection, "edmCollection");
     EntityUtil.CheckArgumentNull(objectCollection, "objectCollection");
     this.m_edmCollection = edmCollection;
     this.m_objectCollection = objectCollection;
     LoadPrimitiveMaps();
 }
            public void ExplicitLoadFromAssembly_checks_only_given_assembly_for_views()
            {
                var mockCache = new Mock<IViewAssemblyCache>();
                var objectItemCollection = new ObjectItemCollection(mockCache.Object);

                objectItemCollection.ExplicitLoadFromAssembly(
                    typeof(object).Assembly, new EdmItemCollection(Enumerable.Empty<XmlReader>()), null);

                mockCache.Verify(m => m.CheckAssembly(typeof(object).Assembly, false), Times.Once());
            }
            public void ImplicitLoadAllReferencedAssemblies_does_not_check_assembly_for_views_if_assembly_filtered()
            {
                var mockCache = new Mock<IViewAssemblyCache>();
                var objectItemCollection = new ObjectItemCollection(mockCache.Object);

                objectItemCollection.ImplicitLoadAllReferencedAssemblies(
                    typeof(object).Assembly, new EdmItemCollection(Enumerable.Empty<XmlReader>()));

                mockCache.Verify(m => m.CheckAssembly(It.IsAny<Assembly>(), It.IsAny<bool>()), Times.Never());
            }
            public void ImplicitLoadAllReferencedAssemblies_checks_assembly_and_references_for_views_if_assembly_not_filtered()
            {
                var mockCache = new Mock<IViewAssemblyCache>();
                var objectItemCollection = new ObjectItemCollection(mockCache.Object);

                objectItemCollection.ImplicitLoadAllReferencedAssemblies(
                    typeof(FactAttribute).Assembly, new EdmItemCollection(Enumerable.Empty<XmlReader>()));

                mockCache.Verify(m => m.CheckAssembly(typeof(FactAttribute).Assembly, true), Times.Once());
            }
        public EFDataModelProvider(object contextInstance, Func<object> contextFactory) {
            ContextFactory = contextFactory;
            RelationshipEndLookup = new Dictionary<long, EFColumnProvider>();
            TableEndLookup = new Dictionary<EntityType, EFTableProvider>();

            _context = (ObjectContext)contextInstance ?? (ObjectContext)CreateContext();
            ContextType = _context.GetType();

            // get a "container" (a scope at the instance level)
            EntityContainer container = _context.MetadataWorkspace.GetEntityContainer(_context.DefaultContainerName, DataSpace.CSpace);
            // load object space metadata
            _context.MetadataWorkspace.LoadFromAssembly(ContextType.Assembly);
            _objectSpaceItems = (ObjectItemCollection)_context.MetadataWorkspace.GetItemCollection(DataSpace.OSpace);

            var tables = new List<TableProvider>();

            // Create a dictionary from entity type to entity set. The entity type should be at the root of any inheritance chain.
            IDictionary<EntityType, EntitySet> entitySetLookup = container.BaseEntitySets.OfType<EntitySet>().ToDictionary(e => e.ElementType);

            // Create a lookup from parent entity to entity
            ILookup<EntityType, EntityType> derivedTypesLookup = _context.MetadataWorkspace.GetItems<EntityType>(DataSpace.CSpace).ToLookup(e => (EntityType)e.BaseType);

            // Keeps track of the current entity set being processed
            EntitySet currentEntitySet = null;

            // Do a DFS to get the inheritance hierarchy in order
            // i.e. Consider the hierarchy
            // null -> Person
            // Person -> Employee, Contact
            // Employee -> SalesPerson, Programmer
            // We'll walk the children in a depth first order -> Person, Employee, SalesPerson, Programmer, Contact.
            var objectStack = new Stack<EntityType>();
            // Start will null (the root of the hierarchy)
            objectStack.Push(null);
            while (objectStack.Any()) {
                EntityType entityType = objectStack.Pop();
                if (entityType != null) {
                    // Update the entity set when we are at another root type (a type without a base type).
                    if (entityType.BaseType == null) {
                        currentEntitySet = entitySetLookup[entityType];
                    }

                    var table = CreateTableProvider(currentEntitySet, entityType);
                    tables.Add(table);
                }

                foreach (EntityType derivedEntityType in derivedTypesLookup[entityType]) {
                    // Push the derived entity types on the stack
                    objectStack.Push(derivedEntityType);
                }
            }

            _tables = tables.AsReadOnly();
        }
 /// <summary>
 /// Constrcutor to create an instance of DefaultObjectMappingItemCollection.
 /// To start with we will create a Schema under which maps will be created.
 /// </summary>
 /// <param name="edmCollection"></param>
 /// <param name="objectCollection"></param>
 public DefaultObjectMappingItemCollection(
     EdmItemCollection edmCollection,
     ObjectItemCollection objectCollection)
     : base(DataSpace.OCSpace)
 {
     Contract.Requires(edmCollection != null);
     Contract.Requires(objectCollection != null);
     m_edmCollection = edmCollection;
     m_objectCollection = objectCollection;
     LoadPrimitiveMaps();
 }
            public void ImplicitLoadAllReferencedAssemblies_does_perform_o_space_lookup_if_o_space_types_not_already_loaded()
            {
                var mockKnownAssemblies = new Mock<KnownAssembliesSet>();
                var objectItemCollection = new ObjectItemCollection(mockKnownAssemblies.Object);

                objectItemCollection.ImplicitLoadAllReferencedAssemblies(
                    typeof(FactAttribute).Assembly(), new EdmItemCollection(Enumerable.Empty<XmlReader>()));

                KnownAssemblyEntry _;
                mockKnownAssemblies.Verify(
                    m => m.TryGetKnownAssembly(typeof(FactAttribute).Assembly(), It.IsAny<object>(), It.IsAny<EdmItemCollection>(), out _));
            }
        /// <summary>
        ///     Constructor to create an instance of DefaultObjectMappingItemCollection.
        ///     To start with we will create a Schema under which maps will be created.
        /// </summary>
        /// <param name="edmCollection"> </param>
        /// <param name="objectCollection"> </param>
        public DefaultObjectMappingItemCollection(
            EdmItemCollection edmCollection,
            ObjectItemCollection objectCollection)
            : base(DataSpace.OCSpace)
        {
            DebugCheck.NotNull(edmCollection);
            DebugCheck.NotNull(objectCollection);

            m_edmCollection = edmCollection;
            m_objectCollection = objectCollection;
            LoadPrimitiveMaps();
        }
            public void ExplicitLoadFromAssembly_does_perform_o_space_lookup_if_o_space_types_not_already_loaded()
            {
                var mockKnownAssemblies = new Mock<KnownAssembliesSet>();
                var objectItemCollection = new ObjectItemCollection(new Mock<IViewAssemblyCache>().Object, mockKnownAssemblies.Object);

                objectItemCollection.ExplicitLoadFromAssembly(
                    typeof(FactAttribute).Assembly, new EdmItemCollection(Enumerable.Empty<XmlReader>()), null);

                KnownAssemblyEntry _;
                mockKnownAssemblies.Verify(
                    m => m.TryGetKnownAssembly(typeof(FactAttribute).Assembly, It.IsAny<object>(), It.IsAny<EdmItemCollection>(), out _));
            }
        // <summary>
        // Constructor to create an instance of DefaultObjectMappingItemCollection.
        // To start with we will create a Schema under which maps will be created.
        // </summary>
        public DefaultObjectMappingItemCollection(
            EdmItemCollection edmCollection,
            ObjectItemCollection objectCollection)
            : base(DataSpace.OCSpace)
        {
            DebugCheck.NotNull(edmCollection);
            DebugCheck.NotNull(objectCollection);

            _edmCollection = edmCollection;
            _objectCollection = objectCollection;

            var cspaceTypes = _edmCollection.GetPrimitiveTypes();
            foreach (var type in cspaceTypes)
            {
                var ospaceType = _objectCollection.GetMappedPrimitiveType(type.PrimitiveTypeKind);
                Debug.Assert(ospaceType != null, "all primitive type must have been loaded");

                AddInternalMapping(new ObjectTypeMapping(ospaceType, type), _clrTypeIndexes, _edmTypeIndexes);
            }
        }
        public void LoadTypes(EdmItemCollection edmItemCollection, ObjectItemCollection objectItemCollection)
        {
            DebugCheck.NotNull(edmItemCollection);
            DebugCheck.NotNull(objectItemCollection);

            foreach (var cSpaceType in edmItemCollection.OfType<EdmType>().Where(
                t => t.BuiltInTypeKind == BuiltInTypeKind.EntityType
                     || t.BuiltInTypeKind == BuiltInTypeKind.EnumType
                     || t.BuiltInTypeKind == BuiltInTypeKind.ComplexType))
            {
                var clrType = cSpaceType.GetClrType();
                if (clrType != null)
                {
                    var oSpaceType = _typeFactory.TryCreateType(clrType, cSpaceType);
                    if (oSpaceType != null)
                    {
                        Debug.Assert(!_typeFactory.CspaceToOspace.ContainsKey(cSpaceType));
                        _typeFactory.CspaceToOspace.Add(cSpaceType, oSpaceType);
                    }
                }
                else
                {
                    Debug.Assert(!(cSpaceType is EntityType || cSpaceType is ComplexType || cSpaceType is EnumType));
                }
            }

            _typeFactory.CreateRelationships(edmItemCollection);

            foreach (var resolve in _typeFactory.ReferenceResolutions)
            {
                resolve();
            }

            foreach (var edmType in _typeFactory.LoadedTypes.Values)
            {
                edmType.SetReadOnly();
            }

            objectItemCollection.AddLoadedTypes(_typeFactory.LoadedTypes);
            objectItemCollection.OSpaceTypesLoaded = true;
        }
		/// <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;
		}
Example #13
0
        internal static bool TryDetermineCSpaceModelType(Type type, MetadataWorkspace workspace, out EdmType modelEdmType)
        {
            Debug.Assert(null != workspace);
            Type nonNullabelType = TypeSystem.GetNonNullableType(type);

            // make sure the workspace knows about T
            workspace.ImplicitLoadAssemblyForType(nonNullabelType, System.Reflection.Assembly.GetCallingAssembly());
            ObjectItemCollection objectItemCollection = (ObjectItemCollection)workspace.GetItemCollection(DataSpace.OSpace);
            EdmType objectEdmType;

            if (objectItemCollection.TryGetItem <EdmType>(nonNullabelType.FullName, out objectEdmType))
            {
                Map map;
                if (workspace.TryGetMap(objectEdmType, DataSpace.OCSpace, out map))
                {
                    ObjectTypeMapping objectMapping = (ObjectTypeMapping)map;
                    modelEdmType = objectMapping.EdmType;
                    return(true);
                }
            }
            modelEdmType = null;
            return(false);
        }
Example #14
0
        /// <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);
        }
Example #15
0
        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 void LoadFromAssembly_checks_only_given_assembly_for_views()
            {
                var mockCache = new Mock<IViewAssemblyCache>();
                var objectItemCollection = new ObjectItemCollection(mockCache.Object);

                objectItemCollection.LoadFromAssembly(typeof(object).Assembly);

                mockCache.Verify(m => m.CheckAssembly(typeof(object).Assembly, false), Times.Once());
            }
 public virtual IEnumerable <GlobalItem> GetObjectItemCollection()
 {
     return
         (_objectItemCollection =
              (ObjectItemCollection)_objectContext.MetadataWorkspace.GetItemCollection(DataSpace.OSpace));
 }
 private static Type GetClrType(MetadataWorkspace metadata, ObjectItemCollection objectItemCollection, EntitySet set) => GetClrType(metadata, objectItemCollection, set.ElementType);
        // <summary>
        // Search for a Mapping metadata with the specified type key.
        // </summary>
        // <param name="identity"> identity of the type </param>
        // <param name="typeSpace"> The dataspace that the type for which map needs to be returned belongs to </param>
        // <param name="ignoreCase"> true for case-insensitive lookup </param>
        // <returns> Returns false if no match found. </returns>
        internal override bool TryGetMap(string identity, DataSpace typeSpace, bool ignoreCase, out MappingBase map)
        {
            EdmType cdmType = null;
            EdmType clrType = null;

            if (typeSpace == DataSpace.CSpace)
            {
                if (ignoreCase)
                {
                    // Get the correct casing of the identity first if we are asked to do ignore case
                    if (!_edmCollection.TryGetItem(identity, true, out cdmType))
                    {
                        map = null;
                        return(false);
                    }

                    identity = cdmType.Identity;
                }

                int index;
                if (_edmTypeIndexes.TryGetValue(identity, out index))
                {
                    map = (MappingBase)this[index];
                    return(true);
                }

                if (cdmType != null
                    ||
                    _edmCollection.TryGetItem(identity, ignoreCase, out cdmType))
                {
                    // If the mapping is not already loaded, then get the mapping ospace type
                    _objectCollection.TryGetOSpaceType(cdmType, out clrType);
                }
            }
            else if (typeSpace == DataSpace.OSpace)
            {
                if (ignoreCase)
                {
                    // Get the correct casing of the identity first if we are asked to do ignore case
                    if (!_objectCollection.TryGetItem(identity, true, out clrType))
                    {
                        map = null;
                        return(false);
                    }

                    identity = clrType.Identity;
                }

                int index;
                if (_clrTypeIndexes.TryGetValue(identity, out index))
                {
                    map = (MappingBase)this[index];
                    return(true);
                }

                if (clrType != null
                    ||
                    _objectCollection.TryGetItem(identity, ignoreCase, out clrType))
                {
                    // If the mapping is not already loaded, get the mapping cspace type
                    var cspaceTypeName = ObjectItemCollection.TryGetMappingCSpaceTypeIdentity(clrType);
                    _edmCollection.TryGetItem(cspaceTypeName, out cdmType);
                }
            }

            if ((clrType == null) ||
                (cdmType == null))
            {
                map = null;
                return(false);
            }
            else
            {
                map = GetDefaultMapping(cdmType, clrType);
                return(true);
            }
        }
        public EFDataModelProvider(object contextInstance, Func <object> contextFactory)
        {
            ContextFactory        = contextFactory;
            RelationshipEndLookup = new Dictionary <long, EFColumnProvider>();
            TableEndLookup        = new Dictionary <EntityType, EFTableProvider>();

            _context    = (ObjectContext)contextInstance ?? (ObjectContext)CreateContext();
            ContextType = _context.GetType();

            // get a "container" (a scope at the instance level)
            EntityContainer container = _context.MetadataWorkspace.GetEntityContainer(_context.DefaultContainerName, DataSpace.CSpace);

            // load object space metadata
            _context.MetadataWorkspace.LoadFromAssembly(ContextType.Assembly);
            _objectSpaceItems = (ObjectItemCollection)_context.MetadataWorkspace.GetItemCollection(DataSpace.OSpace);

            var tables = new List <TableProvider>();

            // Create a dictionary from entity type to entity set. The entity type should be at the root of any inheritance chain.
            IDictionary <EntityType, EntitySet> entitySetLookup = container.BaseEntitySets.OfType <EntitySet>().ToDictionary(e => e.ElementType);

            // Create a lookup from parent entity to entity
            ILookup <EntityType, EntityType> derivedTypesLookup = _context.MetadataWorkspace.GetItems <EntityType>(DataSpace.CSpace).ToLookup(e => (EntityType)e.BaseType);

            // Keeps track of the current entity set being processed
            EntitySet currentEntitySet = null;

            // Do a DFS to get the inheritance hierarchy in order
            // i.e. Consider the hierarchy
            // null -> Person
            // Person -> Employee, Contact
            // Employee -> SalesPerson, Programmer
            // We'll walk the children in a depth first order -> Person, Employee, SalesPerson, Programmer, Contact.
            var objectStack = new Stack <EntityType>();

            // Start will null (the root of the hierarchy)
            objectStack.Push(null);
            while (objectStack.Any())
            {
                EntityType entityType = objectStack.Pop();
                if (entityType != null)
                {
                    // Update the entity set when we are at another root type (a type without a base type).
                    if (entityType.BaseType == null)
                    {
                        currentEntitySet = entitySetLookup[entityType];
                    }

                    var table = CreateTableProvider(currentEntitySet, entityType);
                    tables.Add(table);
                }

                foreach (EntityType derivedEntityType in derivedTypesLookup[entityType])
                {
                    // Push the derived entity types on the stack
                    objectStack.Push(derivedEntityType);
                }
            }

            _tables = tables.AsReadOnly();
        }
 private Type GetClrTypeFromTypeMapping(MetadataWorkspace metadata, ObjectItemCollection objectItemCollection, EntityTypeMapping mapping)
 {
     return GetClrType(metadata, objectItemCollection, mapping.EntityType ?? mapping.IsOfEntityTypes.First());
 }
        public void Can_load_entity_with_property_of_enum_type_from_different_assembly()
        {
            const bool isPOCO = true;

            var enumTypeCsdl = XDocument.Parse(
                @"<Schema xmlns=""http://schemas.microsoft.com/ado/2009/11/edm"" Namespace=""EnumModel"">
  <EnumType Name=""Enum"" IsFlags=""false"" />
</Schema>");

            var entityTypeCsdl = XDocument.Parse(
                @"<Schema xmlns=""http://schemas.microsoft.com/ado/2009/11/edm"" Namespace=""EnumModel"">
  <EntityContainer Name=""EnumModelContainer"">
    <EntitySet Name=""Entity"" EntityType=""EnumModel.Entity"" />
  </EntityContainer>
  <EntityType Name=""Entity"">
    <Key>
      <PropertyRef Name=""Id"" />
    </Key>
    <Property Name=""Id"" Nullable=""false"" Type=""Int32"" />
    <Property Name=""EnumProperty"" Nullable=""false"" Type=""EnumModel.Enum"" />
  </EntityType>
</Schema>");

            var assemblyWithEnumType = BuildAssembly(isPOCO, enumTypeCsdl);
            var assemblyWithEntityType = BuildAssembly(isPOCO, entityTypeCsdl);

            EdmItemCollection edmItemCollection;
            using (var enumTypeReader = enumTypeCsdl.CreateReader())
            {
                using (var entityTypeReader = entityTypeCsdl.CreateReader())
                {
                    edmItemCollection =
                        new EdmItemCollection(
                            new[] { enumTypeReader, entityTypeReader });
                }
            }

            var objectItemCollection = new ObjectItemCollection();
            objectItemCollection.LoadFromAssembly(assemblyWithEnumType, edmItemCollection);
            objectItemCollection.LoadFromAssembly(assemblyWithEntityType, edmItemCollection);

            var workspace = new MetadataWorkspace(
                () => edmItemCollection,
                () => null,
                () => null,
                () => objectItemCollection);

            Assert.Equal(
                "EnumModel.Entity:EnumModel.Entity",
                workspace.GetMap("EnumModel.Entity", DataSpace.OSpace, DataSpace.OCSpace).Identity);
        }
        public EFCodeFirstDataModelProvider(Func<DbContext> dbContextFactory) {
            // First, instantiate a DbContext just to get the type its type
            ContextType = dbContextFactory().GetType();

            // This is the code that gets called anytime an ObjectContext needs to be created
            ContextFactory = () => {
                // Create the DbContext and get the underlying ObjectContext out of it
                DbContext dbContext = dbContextFactory();
                var context = ((IObjectContextAdapter)dbContext).ObjectContext;

                // Set the DefaultContainerName to the context name if it's not set
                if (String.IsNullOrEmpty(context.DefaultContainerName)) {
                    context.DefaultContainerName = ContextType.Name;
                }

                // Load the workspace from the context's assembly
                // See http://social.msdn.microsoft.com/Forums/en-US/adonetefx/thread/53fc5d64-5ff3-4e9f-ae7c-795d1eb750d2
                context.MetadataWorkspace.LoadFromAssembly(ContextType.Assembly);

                return context;
            };

            RelationshipEndLookup = new Dictionary<long, EFCodeFirstColumnProvider>();
            TableEndLookup = new Dictionary<EntityType, EFCodeFirstTableProvider>();

            _objectContext = ContextFactory();

            // get a "container" (a scope at the instance level)
            EntityContainer container = _objectContext.MetadataWorkspace.GetEntityContainer(_objectContext.DefaultContainerName, DataSpace.CSpace);
            _objectSpaceItems = (ObjectItemCollection)_objectContext.MetadataWorkspace.GetItemCollection(DataSpace.OSpace);

            var tables = new List<TableProvider>();

            // Create a dictionary from entity type to entity set. The entity type should be at the root of any inheritance chain.
            IDictionary<EntityType, EntitySet> entitySetLookup = container.BaseEntitySets.OfType<EntitySet>().ToDictionary(e => e.ElementType);

            // Create a lookup from parent entity to entity
            ILookup<EntityType, EntityType> derivedTypesLookup = _objectContext.MetadataWorkspace.GetItems<EntityType>(DataSpace.CSpace).ToLookup(e => (EntityType)e.BaseType);

            // Keeps track of the current entity set being processed
            EntitySet currentEntitySet = null;

            // Do a DFS to get the inheritance hierarchy in order
            // i.e. Consider the hierarchy
            // null -> Person
            // Person -> Employee, Contact
            // Employee -> SalesPerson, Programmer
            // We'll walk the children in a depth first order -> Person, Employee, SalesPerson, Programmer, Contact.
            var objectStack = new Stack<EntityType>();
            // Start will null (the root of the hierarchy)
            objectStack.Push(null);
            while (objectStack.Any()) {
                EntityType entityType = objectStack.Pop();
                if (entityType != null) {
                    // Update the entity set when we are at another root type (a type without a base type).
                    if (entityType.BaseType == null) {
                        currentEntitySet = entitySetLookup[entityType];
                    }

                    // Ignore the special EdmMetadatas table, which is an implementation detail of EF Code First
                    if (currentEntitySet.Name != "EdmMetadatas") {
                        var table = CreateTableProvider(currentEntitySet, entityType);
                        tables.Add(table);
                    }
                }

                foreach (EntityType derivedEntityType in derivedTypesLookup[entityType]) {
                    // Push the derived entity types on the stack
                    objectStack.Push(derivedEntityType);
                }
            }

            _tables = tables.AsReadOnly();
        }
Example #24
0
        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));
        }
        /// <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);
        }
        /// <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;
            var schema = mappingFragment.StoreEntitySet.Schema;

            foreach (var edmProperty in properties)
            {
                if (edmProperty.IsEnumType)
                {
                    references.Add(new EnumReference
                    {
                        ReferencingTableSchema = schema,
                        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
                    {
                        ReferencingTableSchema = schema,
                        ReferencingTable       = table,
                        ReferencingField       = GetColumnName(mappingFragment, edmProperty, nestedProperty),
                        EnumType = objectItemCollection.GetClrType(nestedProperty.EnumType),
                    });
                }
            }

            return(references);
        }
 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);
 }
            public void ImplicitLoadAssemblyForType_checks_assemblies_of_generics_for_views_if_assembly_not_filtered()
            {
                var mockCache = new Mock<IViewAssemblyCache>();
                var objectItemCollection = new ObjectItemCollection(mockCache.Object);

                objectItemCollection.ImplicitLoadAssemblyForType(
                    typeof(Dictionary<FactAttribute, FactAttribute>), new EdmItemCollection(Enumerable.Empty<XmlReader>()));

                mockCache.Verify(m => m.CheckAssembly(typeof(FactAttribute).Assembly, false), Times.Exactly(2));
            }
        private static MetadataWorkspace CreateMetadataWorkspace(XDocument cSpaceCsdl, Assembly assembly, bool isPOCO)
        {

            EdmItemCollection edmItemCollection;
            using (var csdlReader = cSpaceCsdl.CreateReader())
            {
                edmItemCollection = new EdmItemCollection(new[] { csdlReader });
            }

            // assembly can actually be an AssemblyBuilder. The following line ensures that we are 
            // using the actual assembly otherwise an Assert in ObjectItemAttributeAssemblyLoader.LoadType
            // will fire.
            assembly = assembly.GetTypes().First().Assembly();
            var objectItemCollection = new ObjectItemCollection();

            if (isPOCO)
            {
                objectItemCollection.LoadFromAssembly(assembly, edmItemCollection);
            }
            else
            {
                objectItemCollection.LoadFromAssembly(assembly);
            }

            var workspace = new MetadataWorkspace(
                () => edmItemCollection,
                () => null,
                () => null,
                () => objectItemCollection);

            return workspace;
        }
            public void Registering_c_space_or_o_space_does_not_cause_oc_mapping_to_be_registered_if_it_is_already_registered()
            {
                var edmItemCollection = new EdmItemCollection(new[] { XDocument.Parse(Csdl).CreateReader() });
                var objectItemCollection = new ObjectItemCollection();
                var ocMappingItemCollection = new DefaultObjectMappingItemCollection(edmItemCollection, objectItemCollection);

                var workspace = new MetadataWorkspace();
#pragma warning disable 612,618
                workspace.RegisterItemCollection(ocMappingItemCollection);
                workspace.RegisterItemCollection(edmItemCollection);
                workspace.RegisterItemCollection(objectItemCollection);
#pragma warning restore 612,618

                Assert.Same(ocMappingItemCollection, workspace.GetItemCollection(DataSpace.OCSpace));
                Assert.Same(edmItemCollection, workspace.GetItemCollection(DataSpace.CSpace));
                Assert.Same(objectItemCollection, workspace.GetItemCollection(DataSpace.OSpace));
            }
 private static Type GetClrType(MetadataWorkspace metadata, ObjectItemCollection objectItemCollection, EntitySet set)
 {
     return GetClrType(metadata, objectItemCollection, set.ElementType);
 }
 /// <summary>
 ///     Tries to collect the views from the referenced assemblies of Entry assembly.
 /// </summary>
 /// <param name="workspace"> </param>
 private void SerializedCollectViewsFromReferencedAssemblies(
     MetadataWorkspace workspace, Dictionary<EntitySetBase, GeneratedView> extentMappingViews)
 {
     ObjectItemCollection objectCollection;
     ItemCollection itemCollection;
     if (!workspace.TryGetItemCollection(DataSpace.OSpace, out itemCollection))
     {
         //Possible enhancement : Think about achieving the same thing without creating Object Item Collection.
         objectCollection = new ObjectItemCollection();
         itemCollection = objectCollection;
         // The GetEntryAssembly method can return a null reference
         //when a managed assembly has been loaded from an unmanaged application.
         var entryAssembly = Assembly.GetEntryAssembly();
         if (entryAssembly != null)
         {
             objectCollection.ImplicitLoadViewsFromAllReferencedAssemblies(entryAssembly);
         }
     }
     SerializedCollectViewsFromObjectCollection(workspace, extentMappingViews);
 }
Example #33
0
        /// <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);
        }
            public void Four_delegates_constructor_uses_given_delegates_and_sets_up_default_oc_mapping()
            {
                var edmItemCollection = new EdmItemCollection(new[] { XDocument.Parse(_csdlV3).CreateReader() });
                var storeItemCollection = new StoreItemCollection(new[] { XDocument.Parse(_ssdlV3).CreateReader() });
                var objectItemCollection = new ObjectItemCollection();
                var storageMappingItemCollection = LoadMsl(edmItemCollection, storeItemCollection);

                var workspace = new MetadataWorkspace(
                    () => edmItemCollection,
                    () => storeItemCollection,
                    () => storageMappingItemCollection,
                    () => objectItemCollection);

                Assert.Same(edmItemCollection, workspace.GetItemCollection(DataSpace.CSpace));
                Assert.Same(storeItemCollection, workspace.GetItemCollection(DataSpace.SSpace));
                Assert.Same(storageMappingItemCollection, workspace.GetItemCollection(DataSpace.CSSpace));
                Assert.Same(objectItemCollection, workspace.GetItemCollection(DataSpace.OSpace));

                var ocMappingCollection = (DefaultObjectMappingItemCollection)workspace.GetItemCollection(DataSpace.OCSpace);
                Assert.Same(objectItemCollection, ocMappingCollection.ObjectItemCollection);
                Assert.Same(edmItemCollection, ocMappingCollection.EdmItemCollection);
            }
Example #35
0
        internal override bool TryGetMap(
            string identity,
            DataSpace typeSpace,
            bool ignoreCase,
            out MappingBase map)
        {
            EdmType edmType1 = (EdmType)null;
            EdmType edmType2 = (EdmType)null;

            switch (typeSpace)
            {
            case DataSpace.OSpace:
                if (ignoreCase)
                {
                    if (!this._objectCollection.TryGetItem <EdmType>(identity, true, out edmType2))
                    {
                        map = (MappingBase)null;
                        return(false);
                    }
                    identity = edmType2.Identity;
                }
                int index1;
                if (this._clrTypeIndexes.TryGetValue(identity, out index1))
                {
                    map = (MappingBase)this[index1];
                    return(true);
                }
                if (edmType2 != null || this._objectCollection.TryGetItem <EdmType>(identity, ignoreCase, out edmType2))
                {
                    this._edmCollection.TryGetItem <EdmType>(ObjectItemCollection.TryGetMappingCSpaceTypeIdentity(edmType2), out edmType1);
                    break;
                }
                break;

            case DataSpace.CSpace:
                if (ignoreCase)
                {
                    if (!this._edmCollection.TryGetItem <EdmType>(identity, true, out edmType1))
                    {
                        map = (MappingBase)null;
                        return(false);
                    }
                    identity = edmType1.Identity;
                }
                int index2;
                if (this._edmTypeIndexes.TryGetValue(identity, out index2))
                {
                    map = (MappingBase)this[index2];
                    return(true);
                }
                if (edmType1 != null || this._edmCollection.TryGetItem <EdmType>(identity, ignoreCase, out edmType1))
                {
                    this._objectCollection.TryGetOSpaceType(edmType1, out edmType2);
                    break;
                }
                break;
            }
            if (edmType2 == null || edmType1 == null)
            {
                map = (MappingBase)null;
                return(false);
            }
            map = this.GetDefaultMapping(edmType1, edmType2);
            return(true);
        }
            public void ImplicitLoadAssemblyForType_does_not_perform_o_space_lookup_if_o_space_types_already_loaded()
            {
                var mockKnownAssemblies = new Mock<KnownAssembliesSet>();
                var objectItemCollection = new ObjectItemCollection(mockKnownAssemblies.Object);
                objectItemCollection.OSpaceTypesLoaded = true;

                objectItemCollection.ImplicitLoadAssemblyForType(
                    typeof(Dictionary<FactAttribute, FactAttribute>), new EdmItemCollection(Enumerable.Empty<XmlReader>()));

                KnownAssemblyEntry _;
                mockKnownAssemblies.Verify(
                    m => m.TryGetKnownAssembly(It.IsAny<Assembly>(), It.IsAny<object>(), It.IsAny<EdmItemCollection>(), out _),
                    Times.Never());
            }
        private static void ValidateMembersMatch(EdmMember edmMember, EdmMember objectMember)
        {
            Debug.Assert(edmMember.DeclaringType.DataSpace == DataSpace.CSpace, "the cspace member is not on a cspace type");
            Debug.Assert(objectMember.DeclaringType.DataSpace == DataSpace.OSpace, "the ospace member is not on a cspace type");

            // Make sure the property type is the same
            if (edmMember.BuiltInTypeKind
                != objectMember.BuiltInTypeKind)
            {
                throw new MappingException(
                          Strings.Mapping_Default_OCMapping_MemberKind_Mismatch(
                              edmMember.Name, edmMember.DeclaringType.FullName, edmMember.BuiltInTypeKind,
                              objectMember.Name, objectMember.DeclaringType.FullName, objectMember.BuiltInTypeKind));
            }

            // Make sure the member type is the same
            if (edmMember.TypeUsage.EdmType.BuiltInTypeKind
                != objectMember.TypeUsage.EdmType.BuiltInTypeKind)
            {
                throw Error.Mapping_Default_OCMapping_Member_Type_Mismatch(
                          edmMember.TypeUsage.EdmType.Name, edmMember.TypeUsage.EdmType.BuiltInTypeKind, edmMember.Name,
                          edmMember.DeclaringType.FullName,
                          objectMember.TypeUsage.EdmType.Name, objectMember.TypeUsage.EdmType.BuiltInTypeKind, objectMember.Name,
                          objectMember.DeclaringType.FullName);
            }

            if (Helper.IsPrimitiveType(edmMember.TypeUsage.EdmType))
            {
                var memberType = Helper.GetSpatialNormalizedPrimitiveType(edmMember.TypeUsage.EdmType);

                // We expect the CLR primitive type and their corresponding EDM primitive types to have the same primitive type kind (at least for now)
                if (memberType.PrimitiveTypeKind
                    != ((PrimitiveType)objectMember.TypeUsage.EdmType).PrimitiveTypeKind)
                {
                    throw new MappingException(
                              Strings.Mapping_Default_OCMapping_Invalid_MemberType(
                                  edmMember.TypeUsage.EdmType.FullName, edmMember.Name, edmMember.DeclaringType.FullName,
                                  objectMember.TypeUsage.EdmType.FullName, objectMember.Name, objectMember.DeclaringType.FullName));
                }
            }
            else if (Helper.IsEnumType(edmMember.TypeUsage.EdmType))
            {
                Debug.Assert(
                    Helper.IsEnumType(objectMember.TypeUsage.EdmType),
                    "Both types are expected to by EnumTypes. For non-matching types we should have already thrown.");

                ValidateEnumTypeMapping((EnumType)edmMember.TypeUsage.EdmType, (EnumType)objectMember.TypeUsage.EdmType);
            }
            else
            {
                EdmType edmMemberType;
                EdmType objectMemberType;

                if (BuiltInTypeKind.AssociationEndMember
                    == edmMember.BuiltInTypeKind)
                {
                    edmMemberType    = ((RefType)edmMember.TypeUsage.EdmType).ElementType;
                    objectMemberType = ((RefType)objectMember.TypeUsage.EdmType).ElementType;
                }
                else if (BuiltInTypeKind.NavigationProperty == edmMember.BuiltInTypeKind
                         &&
                         Helper.IsCollectionType(edmMember.TypeUsage.EdmType))
                {
                    edmMemberType    = ((CollectionType)edmMember.TypeUsage.EdmType).TypeUsage.EdmType;
                    objectMemberType = ((CollectionType)objectMember.TypeUsage.EdmType).TypeUsage.EdmType;
                }
                else
                {
                    edmMemberType    = edmMember.TypeUsage.EdmType;
                    objectMemberType = objectMember.TypeUsage.EdmType;
                }

                if (edmMemberType.Identity
                    != ObjectItemCollection.TryGetMappingCSpaceTypeIdentity(objectMemberType))
                {
                    throw new MappingException(
                              Strings.Mapping_Default_OCMapping_Invalid_MemberType(
                                  edmMember.TypeUsage.EdmType.FullName, edmMember.Name, edmMember.DeclaringType.FullName,
                                  objectMember.TypeUsage.EdmType.FullName, objectMember.Name, objectMember.DeclaringType.FullName));
                }
            }
        }
                Registering_o_space_causes_oc_mapping_to_also_be_registered_if_it_is_not_already_registered_and_c_space_is_registered()
            {
                var edmItemCollection = new EdmItemCollection(new[] { XDocument.Parse(_csdlV3).CreateReader() });
                var objectItemCollection = new ObjectItemCollection();

                var workspace = new MetadataWorkspace();
#pragma warning disable 612,618
                workspace.RegisterItemCollection(edmItemCollection);
                workspace.RegisterItemCollection(objectItemCollection);
#pragma warning restore 612,618

                Assert.Same(edmItemCollection, workspace.GetItemCollection(DataSpace.CSpace));
                Assert.Same(objectItemCollection, workspace.GetItemCollection(DataSpace.OSpace));

                var ocMappingCollection = (DefaultObjectMappingItemCollection)workspace.GetItemCollection(DataSpace.OCSpace);
                Assert.Same(objectItemCollection, ocMappingCollection.ObjectItemCollection);
                Assert.Same(edmItemCollection, ocMappingCollection.EdmItemCollection);
            }
 private Type GetClrTypeFromTypeMapping(MetadataWorkspace metadata, ObjectItemCollection objectItemCollection, EntityTypeMapping mapping) => GetClrType(metadata, objectItemCollection, mapping.EntityType ?? mapping.IsOfEntityTypes.First());
            public void Registering_o_space_does_not_cause_oc_mapping_to_be_registered_if_c_space_is_not_registered()
            {
                var objectItemCollection = new ObjectItemCollection();

                var workspace = new MetadataWorkspace();
#pragma warning disable 612,618
                workspace.RegisterItemCollection(objectItemCollection);
#pragma warning restore 612,618

                Assert.Same(objectItemCollection, workspace.GetItemCollection(DataSpace.OSpace));
                ItemCollection _;
                Assert.False(workspace.TryGetItemCollection(DataSpace.OCSpace, out _));
            }
 public virtual IEnumerable<GlobalItem> GetObjectItemCollection()
 {
     return
         _objectItemCollection =
         (ObjectItemCollection)_objectContext.MetadataWorkspace.GetItemCollection(DataSpace.OSpace);
 }
        /// <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();
        }
            private static void Item_collections_can_be_registered(MetadataWorkspace workspace)
            {
                var edmItemCollection = new EdmItemCollection(new[] { XDocument.Parse(_csdlV3).CreateReader() });
                var storeItemCollection = new StoreItemCollection(new[] { XDocument.Parse(_ssdlV3).CreateReader() });
                var objectItemCollection = new ObjectItemCollection();
                var storageMappingItemCollection = LoadMsl(edmItemCollection, storeItemCollection);
                var ocMappingItemCollection = new DefaultObjectMappingItemCollection(edmItemCollection, objectItemCollection);

#pragma warning disable 612,618
                workspace.RegisterItemCollection(edmItemCollection);
                workspace.RegisterItemCollection(storeItemCollection);
                workspace.RegisterItemCollection(objectItemCollection);
                workspace.RegisterItemCollection(storageMappingItemCollection);
                workspace.RegisterItemCollection(ocMappingItemCollection);
#pragma warning restore 612,618

                Assert.Same(edmItemCollection, workspace.GetItemCollection(DataSpace.CSpace));
                Assert.Same(storeItemCollection, workspace.GetItemCollection(DataSpace.SSpace));
                Assert.Same(storageMappingItemCollection, workspace.GetItemCollection(DataSpace.CSSpace));
                Assert.Same(objectItemCollection, workspace.GetItemCollection(DataSpace.OSpace));
                Assert.Same(ocMappingItemCollection, workspace.GetItemCollection(DataSpace.OCSpace));
            }
            public void LoadFromAssembly_does_not_perform_o_space_lookup_if_o_space_types_already_loaded()
            {
                var mockKnownAssemblies = new Mock<KnownAssembliesSet>();
                var objectItemCollection = new ObjectItemCollection(new Mock<IViewAssemblyCache>().Object, mockKnownAssemblies.Object);
                objectItemCollection.OSpaceTypesLoaded = true;

                objectItemCollection.LoadFromAssembly(typeof(FactAttribute).Assembly);
                objectItemCollection.LoadFromAssembly(
                    typeof(FactAttribute).Assembly, new EdmItemCollection(Enumerable.Empty<XmlReader>()));
                objectItemCollection.LoadFromAssembly(
                    typeof(FactAttribute).Assembly, new EdmItemCollection(Enumerable.Empty<XmlReader>()), s => { });

                KnownAssemblyEntry _;
                mockKnownAssemblies.Verify(
                    m => m.TryGetKnownAssembly(It.IsAny<Assembly>(), It.IsAny<object>(), It.IsAny<EdmItemCollection>(), out _),
                    Times.Never());
            }