/// <summary>
 /// ScalarColumnMap
 /// </summary>
 /// <param name="columnMap"></param>
 /// <param name="replacementVarMap"></param>
 /// <returns></returns>
 internal override ColumnMap Visit(ScalarColumnMap columnMap, VarMap replacementVarMap)
 {
     return(new ScalarColumnMap(columnMap.Type, columnMap.Name, columnMap.CommandId, columnMap.ColumnPos));
 }
Beispiel #2
0
 internal abstract TResultType Visit(ScalarColumnMap columnMap, TArgType arg);
Beispiel #3
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);
        }
Beispiel #4
0
 internal virtual void Visit(ScalarColumnMap columnMap, TArgType arg)
 {
 }