Esempio n. 1
0
 internal abstract TResultType Visit(SimplePolymorphicColumnMap columnMap, TArgType arg);
        /// <summary>
        /// Creates a column map for a polymorphic type. This method first
        /// creates column maps for each type that is a subtype of the input type,
        /// and then creates a dictionary of typeid value -> column
        /// Finally, a PolymorphicColumnMap is created with these pieces of information
        /// </summary>
        /// <param name="typeInfo">Info about the type</param>
        /// <param name="name">column name</param>
        /// <returns></returns>
        private SimplePolymorphicColumnMap CreatePolymorphicColumnMap(TypeInfo typeInfo, string name)
        {
            // if the typeInfo has a DiscriminatorMap, use TrailingSpaceComparer to ensure that lookups
            // against discriminator values that SQL Server has right-padded (e.g. nchar and char) are properly
            // interpreted
            Dictionary<object, TypedColumnMap> discriminatorMap = new Dictionary<object, TypedColumnMap>(
                typeInfo.RootType.DiscriminatorMap == null ? null : TrailingSpaceComparer.Instance);
            // abstract types may not have discriminator values, but may nonetheless be interesting
            List<TypedColumnMap> allMaps = new List<TypedColumnMap>();

            // SQLBUDT #433011 -- Polymorphic types must construct column maps
            //                    that map to the entire type hierarchy, so we
            //                    need to use the RootType, not the current type.
            TypeInfo rootTypeInfo = typeInfo.RootType;

            // Get the type discriminant column first
            SimpleColumnMap typeIdColumnMap = CreateTypeIdColumnMap(rootTypeInfo.TypeIdProperty);

            // Prepare a place for the constructors to put the columns on the base
            // type, as they identify them.
            TypedColumnMap rootTypeColumnMap = null;

            // process complex/entity types appropriately
            // use the same name for the column 
            if (md.TypeSemantics.IsComplexType(typeInfo.Type))
            {
                rootTypeColumnMap = CreateComplexTypeColumnMap(rootTypeInfo, name, null, discriminatorMap, allMaps);
            }
            else
            {
                rootTypeColumnMap = CreateEntityColumnMap(rootTypeInfo, name, null, discriminatorMap, allMaps, true);
            }

            // Naturally, nothing is simple; we need to walk the rootTypeColumnMap hierarchy
            // and find the column map for the type that we are supposed to have as the base
            // type of this hierarchy.

            TypedColumnMap baseTypeColumnMap = null;
            foreach (TypedColumnMap value in allMaps)
            {
                if (md.TypeSemantics.IsStructurallyEqual(value.Type, typeInfo.Type))
                {
                    baseTypeColumnMap = value;
                    break;
                }
            }
            PlanCompiler.Assert(null != baseTypeColumnMap, "Didn't find requested type in polymorphic type hierarchy?");

            // Create a polymorphic column map
            SimplePolymorphicColumnMap result = new SimplePolymorphicColumnMap(typeInfo.Type, name, baseTypeColumnMap.Properties, typeIdColumnMap, discriminatorMap);
            return result;
        }
        public void TranslateColumnMap_returns_correct_columntypes_and_nullablecolumns_for_discriminated_types()
        {
            var metadataWorkspaceMock = new Mock<MetadataWorkspace>();
            metadataWorkspaceMock.Setup(m => m.GetQueryCacheManager()).Returns(QueryCacheManager.Create());
            
            var typeChoices = new Dictionary<object, TypedColumnMap>();
            var entityColumnMap = (EntityColumnMap)BuildSimpleEntitySetColumnMap(metadataWorkspaceMock).Element;

            typeChoices.Add(true, entityColumnMap);
            var recordMap = new SimplePolymorphicColumnMap(
                entityColumnMap.Type, "E", new ColumnMap[0],
                new ScalarColumnMap(TypeUsage.Create(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Boolean)), "discriminator", 0, 2),
                typeChoices);
            var collectionMap = new SimpleCollectionColumnMap(
                entityColumnMap.Type, "MockCollectionType", recordMap, null, null);

            var factory =
                new Translator().TranslateColumnMap<object>(
                    collectionMap, metadataWorkspaceMock.Object, new SpanIndex(), MergeOption.NoTracking, streaming: false, valueLayer: false);
            Assert.NotNull(factory);

            Assert.Equal(new[] { typeof(int), typeof(int), typeof(bool) }, factory.ColumnTypes);
            Assert.Equal(new[] { true, true, true }, factory.NullableColumns);
        }