internal virtual CollectionColumnMap CreateColumnMapFromReaderAndClrType( DbDataReader reader, Type type, MetadataWorkspace workspace) { DebugCheck.NotNull(reader); DebugCheck.NotNull(type); DebugCheck.NotNull(workspace); // we require a default constructor var constructor = type.GetDeclaredConstructor(); if (type.IsAbstract() || (null == constructor && !type.IsValueType())) { throw new InvalidOperationException(Strings.ObjectContext_InvalidTypeForStoreQuery(type)); } // build a LINQ expression used by result assembly to create results var memberInfo = new List <Tuple <MemberAssignment, int, EdmProperty> >(); foreach (var prop in type.GetInstanceProperties() .Select(p => p.GetPropertyInfoForSet())) { // for enums unwrap the type if nullable var propertyUnderlyingType = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType; var propType = propertyUnderlyingType.IsEnum() ? propertyUnderlyingType.GetEnumUnderlyingType() : prop.PropertyType; EdmType modelType; int ordinal; if (TryGetColumnOrdinalFromReader(reader, prop.Name, out ordinal) && workspace.TryDetermineCSpaceModelType(propType, out modelType) && (Helper.IsScalarType(modelType)) && prop.CanWriteExtended() && prop.GetIndexParameters().Length == 0 && null != prop.Setter()) { 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 var members = new MemberInfo[memberInfo.Count]; var memberBindings = new MemberBinding[memberInfo.Count]; var propertyMaps = new ColumnMap[memberInfo.Count]; var modelProperties = new EdmProperty[memberInfo.Count]; var 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 new InvalidOperationException( Strings.ObjectContext_TwoPropertiesMappedToSameColumn( reader.GetName(memberGroup.Key), String.Join(", ", memberGroup.Select(tuple => tuple.Item3.Name).ToArray()))); } var member = memberGroup.Single(); var assignment = member.Item1; var ordinal = member.Item2; var modelProp = member.Item3; members[i] = assignment.Member; memberBindings[i] = assignment; propertyMaps[i] = new ScalarColumnMap(modelProp.TypeUsage, modelProp.Name, 0, ordinal); modelProperties[i] = modelProp; i++; } var newExpr = null == constructor?Expression.New(type) : Expression.New(constructor); var init = Expression.MemberInit(newExpr, memberBindings); var initMetadata = InitializerMetadata.CreateProjectionInitializer( (EdmItemCollection)workspace.GetItemCollection(DataSpace.CSpace), init); // column map (a collection of rows with InitializerMetadata markup) var rowType = new RowType(modelProperties, initMetadata); var rowMap = new RecordColumnMap( TypeUsage.Create(rowType), "DefaultTypeProjection", propertyMaps, null); CollectionColumnMap collectionMap = new SimpleCollectionColumnMap( rowType.GetCollectionType().TypeUsage, rowType.Name, rowMap, null, null); return(collectionMap); }
/// <summary> /// ScalarColumnMap /// </summary> internal override ColumnMap Visit(ScalarColumnMap columnMap, VarMap replacementVarMap) { return(new ScalarColumnMap(columnMap.Type, columnMap.Name, columnMap.CommandId, columnMap.ColumnPos)); }