private static string GetRowTypeIdentityFromProperties(
            IEnumerable <EdmProperty> properties,
            InitializerMetadata initializerMetadata)
        {
            StringBuilder builder = new StringBuilder("rowtype[");

            if (properties != null)
            {
                int num = 0;
                foreach (EdmProperty property in properties)
                {
                    if (num > 0)
                    {
                        builder.Append(",");
                    }
                    builder.Append("(");
                    builder.Append(property.Name);
                    builder.Append(",");
                    property.TypeUsage.BuildIdentity(builder);
                    builder.Append(")");
                    ++num;
                }
            }
            builder.Append("]");
            if (initializerMetadata != null)
            {
                builder.Append(",").Append(initializerMetadata.Identity);
            }
            return(builder.ToString());
        }
        internal virtual CollectionColumnMap CreateColumnMapFromReaderAndClrType(
            DbDataReader reader,
            Type type,
            MetadataWorkspace workspace)
        {
            ConstructorInfo declaredConstructor = type.GetDeclaredConstructor();

            if (type.IsAbstract() || (ConstructorInfo)null == declaredConstructor && !type.IsValueType())
            {
                throw new InvalidOperationException(Strings.ObjectContext_InvalidTypeForStoreQuery((object)type));
            }
            List <Tuple <MemberAssignment, int, EdmProperty> > source1 = new List <Tuple <MemberAssignment, int, EdmProperty> >();

            foreach (PropertyInfo propertyInfo in type.GetInstanceProperties().Select <PropertyInfo, PropertyInfo>((Func <PropertyInfo, PropertyInfo>)(p => p.GetPropertyInfoForSet())))
            {
                Type type1 = Nullable.GetUnderlyingType(propertyInfo.PropertyType);
                if ((object)type1 == null)
                {
                    type1 = propertyInfo.PropertyType;
                }
                Type    type2 = type1;
                Type    type3 = type2.IsEnum() ? type2.GetEnumUnderlyingType() : propertyInfo.PropertyType;
                int     ordinal;
                EdmType modelEdmType;
                if (ColumnMapFactory.TryGetColumnOrdinalFromReader(reader, propertyInfo.Name, out ordinal) && workspace.TryDetermineCSpaceModelType(type3, out modelEdmType) && (Helper.IsScalarType(modelEdmType) && propertyInfo.CanWriteExtended()) && (propertyInfo.GetIndexParameters().Length == 0 && (MethodInfo)null != propertyInfo.Setter()))
                {
                    source1.Add(Tuple.Create <MemberAssignment, int, EdmProperty>(Expression.Bind((MemberInfo)propertyInfo, (Expression)Expression.Parameter(propertyInfo.PropertyType, "placeholder")), ordinal, new EdmProperty(propertyInfo.Name, TypeUsage.Create(modelEdmType))));
                }
            }
            MemberInfo[]    memberInfoArray    = new MemberInfo[source1.Count];
            MemberBinding[] memberBindingArray = new MemberBinding[source1.Count];
            ColumnMap[]     properties         = new ColumnMap[source1.Count];
            EdmProperty[]   edmPropertyArray   = new EdmProperty[source1.Count];
            int             index = 0;

            foreach (IGrouping <int, Tuple <MemberAssignment, int, EdmProperty> > source2 in (IEnumerable <IGrouping <int, Tuple <MemberAssignment, int, EdmProperty> > >)source1.GroupBy <Tuple <MemberAssignment, int, EdmProperty>, int>((Func <Tuple <MemberAssignment, int, EdmProperty>, int>)(tuple => tuple.Item2)).OrderBy <IGrouping <int, Tuple <MemberAssignment, int, EdmProperty> >, int>((Func <IGrouping <int, Tuple <MemberAssignment, int, EdmProperty> >, int>)(tuple => tuple.Key)))
            {
                if (source2.Count <Tuple <MemberAssignment, int, EdmProperty> >() != 1)
                {
                    throw new InvalidOperationException(Strings.ObjectContext_TwoPropertiesMappedToSameColumn((object)reader.GetName(source2.Key), (object)string.Join(", ", source2.Select <Tuple <MemberAssignment, int, EdmProperty>, string>((Func <Tuple <MemberAssignment, int, EdmProperty>, string>)(tuple => tuple.Item3.Name)).ToArray <string>())));
                }
                Tuple <MemberAssignment, int, EdmProperty> tuple1 = source2.Single <Tuple <MemberAssignment, int, EdmProperty> >();
                MemberAssignment memberAssignment = tuple1.Item1;
                int         columnPos             = tuple1.Item2;
                EdmProperty edmProperty           = tuple1.Item3;
                memberInfoArray[index]    = memberAssignment.Member;
                memberBindingArray[index] = (MemberBinding)memberAssignment;
                properties[index]         = (ColumnMap) new ScalarColumnMap(edmProperty.TypeUsage, edmProperty.Name, 0, columnPos);
                edmPropertyArray[index]   = edmProperty;
                ++index;
            }
            MemberInitExpression initExpression        = Expression.MemberInit((ConstructorInfo)null == declaredConstructor ? Expression.New(type) : Expression.New(declaredConstructor), memberBindingArray);
            InitializerMetadata  projectionInitializer = InitializerMetadata.CreateProjectionInitializer((EdmItemCollection)workspace.GetItemCollection(DataSpace.CSpace), initExpression);
            RowType         rowType         = new RowType((IEnumerable <EdmProperty>)edmPropertyArray, projectionInitializer);
            RecordColumnMap recordColumnMap = new RecordColumnMap(TypeUsage.Create((EdmType)rowType), "DefaultTypeProjection", properties, (SimpleColumnMap)null);

            return((CollectionColumnMap) new SimpleCollectionColumnMap(rowType.GetCollectionType().TypeUsage, rowType.Name, (ColumnMap)recordColumnMap, (SimpleColumnMap[])null, (SimpleColumnMap[])null));
        }
Пример #3
0
 internal InitializerMetadata GetCanonicalInitializerMetadata(
     InitializerMetadata metadata)
 {
     if (this._getCanonicalInitializerMetadataMemoizer == null)
     {
         Interlocked.CompareExchange <Memoizer <InitializerMetadata, InitializerMetadata> >(ref this._getCanonicalInitializerMetadataMemoizer, new Memoizer <InitializerMetadata, InitializerMetadata>((Func <InitializerMetadata, InitializerMetadata>)(m => m), (IEqualityComparer <InitializerMetadata>)EqualityComparer <InitializerMetadata> .Default), (Memoizer <InitializerMetadata, InitializerMetadata>)null);
     }
     return(this._getCanonicalInitializerMetadataMemoizer.Evaluate(metadata));
 }
        internal static RowType CreateRowType(
            IEnumerable <KeyValuePair <string, TypeUsage> > columns,
            InitializerMetadata initializerMetadata)
        {
            List <EdmProperty> edmPropertyList = new List <EdmProperty>();

            foreach (KeyValuePair <string, TypeUsage> column in columns)
            {
                edmPropertyList.Add(new EdmProperty(column.Key, column.Value));
            }
            return(new RowType((IEnumerable <EdmProperty>)edmPropertyList, initializerMetadata));
        }
 internal RowType(IEnumerable <EdmProperty> properties, InitializerMetadata initializerMetadata)
     : base(RowType.GetRowTypeIdentityFromProperties(RowType.CheckProperties(properties), initializerMetadata), "Transient", ~DataSpace.OSpace)
 {
     if (properties != null)
     {
         foreach (EdmProperty property in properties)
         {
             this.AddProperty(property);
         }
     }
     this._initializerMetadata = initializerMetadata;
     this.SetReadOnly();
 }
        internal void Append(string prefix, TypeUsage type)
        {
            if (type == null)
            {
                return;
            }
            InitializerMetadata initializerMetadata;

            if (InitializerMetadata.TryGetInitializerMetadata(type, out initializerMetadata))
            {
                initializerMetadata.AppendColumnMapKey(this);
            }
            this.Append(prefix, type.EdmType);
        }
Пример #7
0
        /// <summary>
        /// Given an InitializerMetadata instance, returns the canonical version of that instance.
        /// This allows us to avoid compiling materialization delegates repeatedly for the same
        /// pattern.
        /// </summary>
        internal InitializerMetadata GetCanonicalInitializerMetadata(InitializerMetadata metadata)
        {
            if (null == _getCanonicalInitializerMetadataMemoizer)
            {
                // We memoize the identity function because the first evaluation of the function establishes
                // the canonical 'reference' for the initializer metadata with a particular 'value'.
                Interlocked.CompareExchange(ref _getCanonicalInitializerMetadataMemoizer, new Memoizer <InitializerMetadata, InitializerMetadata>(
                                                m => m, EqualityComparer <InitializerMetadata> .Default), null);
            }

            // check if an equivalent has already been registered
            InitializerMetadata canonical = _getCanonicalInitializerMetadataMemoizer.Evaluate(metadata);

            return(canonical);
        }
Пример #8
0
 internal void Append(string prefix, TypeUsage type)
 {
     if (null != type)
     {
         // LINQ has anonymous types that aren't going to show up in our
         // metadata workspace, and we don't want to hydrate a record when
         // we need an anonymous type.  LINQ solves this by annotating the
         // edmType with some additional information, which we'll pick up
         // here.
         InitializerMetadata initializer;
         if (InitializerMetadata.TryGetInitializerMetadata(type, out initializer))
         {
             initializer.AppendColumnMapKey(this);
         }
         Append(prefix, type.EdmType);
     }
 }
Пример #9
0
        /// <summary>
        /// Initializes a RowType with the given members and initializer metadata 
        /// </summary>
        internal RowType(IEnumerable<EdmProperty> properties, InitializerMetadata initializerMetadata)
            : base(GetRowTypeIdentityFromProperties(CheckProperties(properties), initializerMetadata), EdmConstants.TransientNamespace, (DataSpace)(-1))
        {
            // Initialize the properties. 
            if (null != properties)
            {
                foreach (EdmProperty property in properties)
                {
                    this.AddProperty(property);
                }
            }

            _initializerMetadata = initializerMetadata;

            // Row types are immutable, so now that we're done initializing, set it
            // to be read-only.
            SetReadOnly();
        }
Пример #10
0
        /// <summary>
        /// Initializes a RowType with the given members and initializer metadata
        /// </summary>
        internal RowType(IEnumerable <EdmProperty> properties, InitializerMetadata initializerMetadata)
            : base(GetRowTypeIdentityFromProperties(CheckProperties(properties), initializerMetadata), EdmConstants.TransientNamespace, (DataSpace)(-1))
        {
            // Initialize the properties.
            if (null != properties)
            {
                foreach (EdmProperty property in properties)
                {
                    this.AddProperty(property);
                }
            }

            _initializerMetadata = initializerMetadata;

            // Row types are immutable, so now that we're done initializing, set it
            // to be read-only.
            SetReadOnly();
        }
        /// <summary>
        /// Given an InitializerMetadata instance, returns the canonical version of that instance.
        /// This allows us to avoid compiling materialization delegates repeatedly for the same
        /// pattern.
        /// </summary>
        internal InitializerMetadata GetCanonicalInitializerMetadata(InitializerMetadata metadata)
        {
            if (null == _getCanonicalInitializerMetadataMemoizer)
            {
                // We memoize the identity function because the first evaluation of the function establishes
                // the canonical 'reference' for the initializer metadata with a particular 'value'.
                Interlocked.CompareExchange(ref _getCanonicalInitializerMetadataMemoizer, new Memoizer<InitializerMetadata, InitializerMetadata>(
                    m => m, EqualityComparer<InitializerMetadata>.Default), null);
            }

            // check if an equivalent has already been registered
            InitializerMetadata canonical = _getCanonicalInitializerMetadataMemoizer.Evaluate(metadata);
            return canonical;
        }
Пример #12
0
        // <summary>
        // Calculates the row type identity that would result from
        // a given set of properties.
        // </summary>
        // <param name="properties"> The properties that determine the row type's structure </param>
        // <param name="initializerMetadata"> Metadata describing materialization of this row type </param>
        // <returns> A string that identifies the row type </returns>
        private static string GetRowTypeIdentityFromProperties(IEnumerable<EdmProperty> properties, InitializerMetadata initializerMetadata)
        {
            // The row type identity is formed as follows:
            // "rowtype[" + a comma-separated list of property identities + "]"
            var identity = new StringBuilder("rowtype[");

            if (null != properties)
            {
                var i = 0;
                // For each property, append the type name and facets.
                foreach (var property in properties)
                {
                    if (i > 0)
                    {
                        identity.Append(",");
                    }
                    identity.Append("(");
                    identity.Append(property.Name);
                    identity.Append(",");
                    property.TypeUsage.BuildIdentity(identity);
                    identity.Append(")");
                    i++;
                }
            }
            identity.Append("]");

            if (null != initializerMetadata)
            {
                identity.Append(",").Append(initializerMetadata.Identity);
            }

            return identity.ToString();
        }
Пример #13
0
        /// <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);
        }
Пример #14
0
 internal void ValidateInitializerMetadata(InitializerMetadata metadata)
 {
     DebugCheck.NotNull(metadata);
     InitializerMetadata existingMetadata;
     if (_initializers != null
         && _initializers.TryGetValue(metadata.ClrType, out existingMetadata))
     {
         // Verify the initializers are compatible.
         if (!metadata.Equals(existingMetadata))
         {
             throw new NotSupportedException(
                 Strings.ELinq_UnsupportedHeterogeneousInitializers(
                     DescribeClrType(metadata.ClrType)));
         }
     }
     else
     {
         // Register the metadata so that subsequent initializers for this type can be verified.
         if (_initializers == null)
         {
             _initializers = new Dictionary<Type, InitializerMetadata>();
         }
         _initializers.Add(metadata.ClrType, metadata);
     }
 }
Пример #15
0
 private static DbNewInstanceExpression CreateNewRowExpression(
     List<KeyValuePair<string, DbExpression>> columns, InitializerMetadata initializerMetadata)
 {
     var propertyValues = new List<DbExpression>(columns.Count);
     var properties = new List<EdmProperty>(columns.Count);
     for (var i = 0; i < columns.Count; i++)
     {
         var column = columns[i];
         propertyValues.Add(column.Value);
         properties.Add(new EdmProperty(column.Key, column.Value.ResultType));
     }
     var rowType = new RowType(properties, initializerMetadata);
     var typeUsage = TypeUsage.Create(rowType);
     return typeUsage.New(propertyValues);
 }
Пример #16
0
        internal static RowType CreateRowType(IEnumerable <KeyValuePair <string, TypeUsage> > columns, InitializerMetadata initializerMetadata)
        {
            var rowElements = new List <EdmProperty>();

            foreach (var kvp in columns)
            {
                rowElements.Add(new EdmProperty(kvp.Key, kvp.Value));
            }
            return(new RowType(rowElements, initializerMetadata));
        }
Пример #17
0
        /// <summary>
        /// Calculates the row type identity that would result from
        /// a given set of properties.
        /// </summary>
        /// <param name="properties">The properties that determine the row type's structure</param>
        /// <param name="initializerMetadata">Metadata describing materialization of this row type</param>
        /// <returns>A string that identifies the row type</returns>
        private static string GetRowTypeIdentityFromProperties(IEnumerable <EdmProperty> properties, InitializerMetadata initializerMetadata)
        {
            // The row type identity is formed as follows:
            // "rowtype[" + a comma-separated list of property identities + "]"
            StringBuilder identity = new StringBuilder("rowtype[");

            if (null != properties)
            {
                int i = 0;
                // For each property, append the type name and facets.
                foreach (EdmProperty property in properties)
                {
                    if (i > 0)
                    {
                        identity.Append(",");
                    }
                    identity.Append("(");
                    identity.Append(property.Name);
                    identity.Append(",");
                    property.TypeUsage.BuildIdentity(identity);
                    identity.Append(")");
                    i++;
                }
            }
            identity.Append("]");

            if (null != initializerMetadata)
            {
                identity.Append(",").Append(initializerMetadata.Identity);
            }

            return(identity.ToString());
        }
Пример #18
0
 internal void ValidateInitializerMetadata(InitializerMetadata metadata)
 {
     Debug.Assert(null != metadata);
     InitializerMetadata existingMetadata;
     if (_initializers != null && _initializers.TryGetValue(metadata.ClrType, out existingMetadata))
     {
         // Verify the initializers are compatible.
         if (!metadata.Equals(existingMetadata))
         {
             throw EntityUtil.NotSupported(System.Data.Entity.Strings.ELinq_UnsupportedHeterogeneousInitializers(
                 ExpressionConverter.DescribeClrType(metadata.ClrType)));
         }
     }
     else
     {
         // Register the metadata so that subsequent initializers for this type can be verified.
         if (_initializers == null)
         {
             _initializers = new Dictionary<Type, InitializerMetadata>();
         }
         _initializers.Add(metadata.ClrType, metadata);
     }
 }