public void TranslateColumnMap_returns_correct_columntypes_and_nullablecolumns_for_anonymous_types()
        {
            var metadataWorkspaceMock = new Mock <MetadataWorkspace>();

            metadataWorkspaceMock.Setup(m => m.GetQueryCacheManager()).Returns(QueryCacheManager.Create());
            var edmProperties = new []
            {
                new EdmProperty("P1Int", TypeUsage.Create(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32),
                                                          new FacetValues {
                    Nullable = false
                })),
                new EdmProperty("P2Bool", TypeUsage.Create(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Boolean)))
            };

            var cSpaceEntityType = new RowType(edmProperties);
            var entityTypeUsage  = TypeUsage.Create(cSpaceEntityType);
            var recordMap        = new RecordColumnMap(
                entityTypeUsage, "E",
                new[] { new ScalarColumnMap(cSpaceEntityType.Properties[0].TypeUsage, cSpaceEntityType.Properties[0].Name, 0, 0) },
                new ScalarColumnMap(cSpaceEntityType.Properties[1].TypeUsage, cSpaceEntityType.Properties[1].Name, 0, 1));
            var collectionMap = new SimpleCollectionColumnMap(
                entityTypeUsage, "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), null }, factory.ColumnTypes);
            Assert.Equal(new[] { true, true }, factory.NullableColumns);
        }
 internal virtual void Visit(RecordColumnMap columnMap, TArgType arg)
 {
     columnMap.NullSentinel?.Accept <TArgType>(this, arg);
     foreach (ColumnMap property in columnMap.Properties)
     {
         property.Accept <TArgType>(this, arg);
     }
 }
Beispiel #3
0
        internal virtual void Visit(RecordColumnMap columnMap, TArgType arg)
        {
            ColumnMap nullSentinel = columnMap.NullSentinel;

            if (null != nullSentinel)
            {
                nullSentinel.Accept(this, arg);
            }
            foreach (var p in columnMap.Properties)
            {
                p.Accept(this, arg);
            }
        }
Beispiel #4
0
        /// <summary>
        /// RecordColumnMap
        /// </summary>
        /// <param name="columnMap"></param>
        /// <param name="translationDelegate"></param>
        /// <returns></returns>
        internal override ColumnMap Visit(RecordColumnMap columnMap, ColumnMapTranslatorTranslationDelegate translationDelegate)
        {
            SimpleColumnMap newNullSentinel = columnMap.NullSentinel;

            if (null != newNullSentinel)
            {
                newNullSentinel = (SimpleColumnMap)translationDelegate(newNullSentinel);
            }

            VisitList(columnMap.Properties, translationDelegate);

            if (columnMap.NullSentinel != newNullSentinel)
            {
                columnMap = new RecordColumnMap(columnMap.Type, columnMap.Name, columnMap.Properties, newNullSentinel);
            }
            return(translationDelegate(columnMap));
        }
Beispiel #5
0
        /// <summary>
        /// Create a column map for a record type. Simply iterates through the
        /// list of fields, and produces a column map for each field
        /// </summary>
        /// <param name="typeInfo">Type information for the record type</param>
        /// <param name="name">column name</param>
        /// <returns></returns>
        private RecordColumnMap CreateRecordColumnMap(TypeInfo typeInfo, string name)
        {
            PlanCompiler.Assert(typeInfo.Type.EdmType is md.RowType, "not RowType");
            SimpleColumnMap nullSentinelColumnMap = null;

            if (typeInfo.HasNullSentinelProperty)
            {
                nullSentinelColumnMap = CreateSimpleColumnMap(md.Helper.GetModelTypeUsage(typeInfo.NullSentinelProperty), c_NullSentinelColumnName);
            }

            md.ReadOnlyMetadataCollection <md.EdmProperty> properties = TypeHelpers.GetProperties(typeInfo.Type);
            ColumnMap[] propertyColumnMapList = new ColumnMap[properties.Count];
            for (int i = 0; i < propertyColumnMapList.Length; ++i)
            {
                md.EdmMember property = properties[i];
                propertyColumnMapList[i] = CreateColumnMap(md.Helper.GetModelTypeUsage(property), property.Name);
            }

            RecordColumnMap result = new RecordColumnMap(typeInfo.Type, name, propertyColumnMapList, nullSentinelColumnMap);

            return(result);
        }
        /// <summary>
        /// Create a column map for a record type. Simply iterates through the
        /// list of fields, and produces a column map for each field
        /// </summary>
        /// <param name="typeInfo">Type information for the record type</param>
        /// <param name="name">column name</param>
        /// <returns></returns>
        private RecordColumnMap CreateRecordColumnMap(TypeInfo typeInfo, string name)
        {
            PlanCompiler.Assert(typeInfo.Type.EdmType is md.RowType, "not RowType");
            SimpleColumnMap nullSentinelColumnMap = null;
            if (typeInfo.HasNullSentinelProperty)
            {
                nullSentinelColumnMap = CreateSimpleColumnMap(md.Helper.GetModelTypeUsage(typeInfo.NullSentinelProperty), c_NullSentinelColumnName);
            }

            md.ReadOnlyMetadataCollection<md.EdmProperty> properties = TypeHelpers.GetProperties(typeInfo.Type);
            ColumnMap[] propertyColumnMapList = new ColumnMap[properties.Count];
            for (int i = 0; i < propertyColumnMapList.Length; ++i)
            {
                md.EdmMember property = properties[i];
                propertyColumnMapList[i] = CreateColumnMap(md.Helper.GetModelTypeUsage(property), property.Name);
            }

            RecordColumnMap result = new RecordColumnMap(typeInfo.Type, name, propertyColumnMapList, nullSentinelColumnMap);
            return result;
        }
Beispiel #7
0
 internal abstract TResultType Visit(RecordColumnMap columnMap, TArgType arg);
        public void TranslateColumnMap_returns_correct_columntypes_and_nullablecolumns_for_anonymous_types()
        {
            var metadataWorkspaceMock = new Mock<MetadataWorkspace>();
            metadataWorkspaceMock.Setup(m => m.GetQueryCacheManager()).Returns(QueryCacheManager.Create());
            var edmProperties = new []
                {
                    new EdmProperty("P1Int", TypeUsage.Create(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32),
                        new FacetValues { Nullable = false })),
                    new EdmProperty("P2Bool", TypeUsage.Create(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Boolean)))
                };

            var cSpaceEntityType = new RowType(edmProperties);
            var entityTypeUsage = TypeUsage.Create(cSpaceEntityType);
            var recordMap = new RecordColumnMap(
                entityTypeUsage, "E",
                new[] { new ScalarColumnMap(cSpaceEntityType.Properties[0].TypeUsage, cSpaceEntityType.Properties[0].Name, 0, 0) },
                new ScalarColumnMap(cSpaceEntityType.Properties[1].TypeUsage, cSpaceEntityType.Properties[1].Name, 0, 1));
            var collectionMap = new SimpleCollectionColumnMap(
                entityTypeUsage, "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), null }, factory.ColumnTypes);
            Assert.Equal(new[] { true, true }, factory.NullableColumns);
        }
        /// <summary>
        /// Build the collectionColumnMap from a store datareader, a type and an entitySet.
        /// </summary>
        /// <param name="storeDataReader"></param>
        /// <param name="edmType"></param>
        /// <param name="entitySet"></param>
        /// <returns></returns>
        internal static CollectionColumnMap CreateColumnMapFromReaderAndType(DbDataReader storeDataReader, EdmType edmType, EntitySet entitySet, Dictionary<string, FunctionImportReturnTypeStructuralTypeColumnRenameMapping> renameList)
        {
            Debug.Assert(Helper.IsEntityType(edmType) || null == entitySet, "The specified non-null EntitySet is incompatible with the EDM type specified.");

            // Next, build the ColumnMap directly from the edmType and entitySet provided.
            ColumnMap[] propertyColumnMaps = GetColumnMapsForType(storeDataReader, edmType, renameList);
            ColumnMap elementColumnMap = null;

            // NOTE: We don't have a null sentinel here, because the stored proc won't 
            //       return one anyway; we'll just presume the data's always there.
            if (Helper.IsRowType(edmType))
            {
                elementColumnMap = new RecordColumnMap(TypeUsage.Create(edmType), edmType.Name, propertyColumnMaps, null);
            }
            else if (Helper.IsComplexType(edmType))
            {
                elementColumnMap = new ComplexTypeColumnMap(TypeUsage.Create(edmType), edmType.Name, propertyColumnMaps, null);
            }
            else if (Helper.IsScalarType(edmType))
            {
                if (storeDataReader.FieldCount != 1)
                {
                    throw EntityUtil.CommandExecutionDataReaderFieldCountForScalarType();
                }
                elementColumnMap = new ScalarColumnMap(TypeUsage.Create(edmType), edmType.Name, 0, 0);
            }
            else if (Helper.IsEntityType(edmType))
            {
                elementColumnMap = CreateEntityTypeElementColumnMap(storeDataReader, edmType, entitySet, propertyColumnMaps, null/*renameList*/);
            }
            else
            {
                Debug.Assert(false, "unexpected edmType?");
            }
            CollectionColumnMap collection = new SimpleCollectionColumnMap(edmType.GetCollectionType().TypeUsage, edmType.Name, elementColumnMap, null, null);
            return collection;
        }
        /// <summary>
        /// Requires: a public type with a public, default constructor. Returns a column map initializing the type
        /// and all properties of the type with a public setter taking a primitive type and having a corresponding 
        /// column in the reader.
        /// </summary>
        internal static CollectionColumnMap CreateColumnMapFromReaderAndClrType(DbDataReader reader, Type type, MetadataWorkspace workspace)
        {
            Debug.Assert(null != reader);
            Debug.Assert(null != type);
            Debug.Assert(null != workspace);

            // we require a default constructor
            ConstructorInfo constructor = type.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
                null, Type.EmptyTypes, null);
            if (type.IsAbstract || (null == constructor && !type.IsValueType))
            {
                throw EntityUtil.InvalidOperation(
                    Strings.ObjectContext_InvalidTypeForStoreQuery(type));
            }

            // build a LINQ expression used by result assembly to create results
            var memberInfo = new List<Tuple<MemberAssignment, int, EdmProperty>>();
            foreach (PropertyInfo prop in type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
            {
                // for enums unwrap the type if nullable
                var propertyUnderlyingType = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType;
                Type propType = propertyUnderlyingType.IsEnum ? propertyUnderlyingType.GetEnumUnderlyingType() : prop.PropertyType;

                EdmType modelType;
                int ordinal;
                if (TryGetColumnOrdinalFromReader(reader, prop.Name, out ordinal) &&
                    MetadataHelper.TryDetermineCSpaceModelType(propType, workspace, out modelType) &&
                    (Helper.IsScalarType(modelType)) &&
                    prop.CanWrite && prop.GetIndexParameters().Length == 0 && null != prop.GetSetMethod(/* nonPublic */true))
                {
                    memberInfo.Add(Tuple.Create(
                        Expression.Bind(prop, Expression.Parameter(prop.PropertyType, "placeholder")),
                        ordinal,
                        new EdmProperty(prop.Name, TypeUsage.Create(modelType))));
                }
            }
            // initialize members in the order in which they appear in the reader
            MemberInfo[] members = new MemberInfo[memberInfo.Count];
            MemberBinding[] memberBindings = new MemberBinding[memberInfo.Count];
            ColumnMap[] propertyMaps = new ColumnMap[memberInfo.Count];
            EdmProperty[] modelProperties = new EdmProperty[memberInfo.Count];
            int i = 0;
            foreach (var memberGroup in memberInfo.GroupBy(tuple => tuple.Item2).OrderBy(tuple => tuple.Key))
            {
                // make sure that a single column isn't contributing to multiple properties
                if (memberGroup.Count() != 1)
                {
                    throw EntityUtil.InvalidOperation(Strings.ObjectContext_TwoPropertiesMappedToSameColumn(
                        reader.GetName(memberGroup.Key), 
                        String.Join(", ", memberGroup.Select(tuple => tuple.Item3.Name).ToArray())));
                }

                var member = memberGroup.Single();
                MemberAssignment assignment = member.Item1;
                int ordinal = member.Item2;
                EdmProperty modelProp = member.Item3;
                
                members[i] = assignment.Member;
                memberBindings[i] = assignment;
                propertyMaps[i] = new ScalarColumnMap(modelProp.TypeUsage, modelProp.Name, 0, ordinal);
                modelProperties[i] = modelProp;
                i++;
            }
            NewExpression newExpr = null == constructor ? Expression.New(type) : Expression.New(constructor);
            MemberInitExpression init = Expression.MemberInit(newExpr, memberBindings);
            InitializerMetadata initMetadata = InitializerMetadata.CreateProjectionInitializer(
                (EdmItemCollection)workspace.GetItemCollection(DataSpace.CSpace), init, members);

            // column map (a collection of rows with InitializerMetadata markup)
            RowType rowType = new RowType(modelProperties, initMetadata);
            RecordColumnMap rowMap = new RecordColumnMap(TypeUsage.Create(rowType),
                "DefaultTypeProjection", propertyMaps, null);
            CollectionColumnMap collectionMap = new SimpleCollectionColumnMap(rowType.GetCollectionType().TypeUsage, 
                rowType.Name, rowMap, null, null);
            return collectionMap;
        }
Beispiel #11
0
 internal override void Visit(RecordColumnMap columnMap, int dummy)
 {
     Append("R-", columnMap.Type);
     Append(",N", columnMap.NullSentinel);
     Append(",P", columnMap.Properties);
 }
 internal override void Visit(RecordColumnMap columnMap, int dummy)
 {
     this.Append("R-", columnMap.Type);
     this.Append(",N", (ColumnMap)columnMap.NullSentinel);
     this.Append(",P", (IEnumerable <ColumnMap>)columnMap.Properties);
 }