public void EdmModel_NameIsTooLong_not_triggered_for_row_and_collection_types()
        {
            var intType = PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32);

            var properties = new EdmProperty[100];

            for (int i = 0; i < 100; i++)
            {
                properties[i] = EdmProperty.Primitive("Property" + i, intType);
            }

            var rowType = new RowType(properties);

            foreach (var type in new EdmType[] { rowType, rowType.GetCollectionType() })
            {
                var validationContext
                    = new EdmModelValidationContext(new EdmModel(DataSpace.SSpace), true);
                DataModelErrorEventArgs errorEventArgs = null;
                validationContext.OnError += (_, e) => errorEventArgs = e;

                EdmModelSyntacticValidationRules
                .EdmModel_NameIsTooLong
                .Evaluate(validationContext, type);

                Assert.Null(errorEventArgs);
            }
        }
        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));
        }
        public void EdmType_SystemNamespaceEncountered_not_triggered_for_row_and_collection_types()
        {
            var rowType =
                new RowType(new[] { EdmProperty.Primitive("Property", PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32)) });

            foreach (var type in new EdmType[] { rowType, rowType.GetCollectionType() })
            {
                var validationContext
                    = new EdmModelValidationContext(new EdmModel(DataSpace.SSpace), true);
                DataModelErrorEventArgs errorEventArgs = null;
                validationContext.OnError += (_, e) => errorEventArgs = e;

                EdmModelSemanticValidationRules
                .EdmType_SystemNamespaceEncountered
                .Evaluate(validationContext, type);

                Assert.Null(errorEventArgs);
            }
        }
Example #4
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);
        }
        private static IList <FunctionParameter> GetStoreReturnParameters(DbModel model, MethodInfo methodInfo, FunctionAttribute functionAttribute)
        {
            if (methodInfo.ReturnParameter == null || (methodInfo.ReturnParameter.ParameterType == typeof(void) && functionAttribute.Type != FunctionType.StoredProcedure))
            {
                throw new NotSupportedException(string.Format("The return type of {0} is not supported.", methodInfo.Name));
            }

            var returnParameterAttribute = methodInfo.ReturnParameter.GetCustomAttribute <ParameterAttribute>();

            //var returnTypeAttributes = methodInfo.GetCustomAttributes<ResultTypeAttribute>();

            if (functionAttribute.Type == FunctionType.StoredProcedure || functionAttribute.Type == FunctionType.TableValuedFunction)
            {
                if (returnParameterAttribute != null)
                {
                    throw new NotSupportedException(string.Format("ParameterAttribute for return value of method {0} is not supported.", methodInfo.Name));
                }
            }

            if (functionAttribute.Type == FunctionType.StoredProcedure || methodInfo.ReturnType == typeof(void))
            {
                //Stored Procedure
                return(new FunctionParameter[0]);
                //return new[]
                //{
                //	FunctionParameter.Create("ReturnType", PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32), ParameterMode.ReturnValue)
                //};
            }

            //if (returnTypeAttributes.Length > 0)
            //	throw new NotSupportedException(string.Format("ResultTypeAttribute for method {0} is not supported.", methodInfo.Name));

            if (functionAttribute.Type == FunctionType.TableValuedFunction)
            {
                //if (returnParameterAttribute != null)
                //	throw new NotSupportedException(string.Format("ParameterAttribute for return value of method {0} is not supported.", methodInfo.Name));

                /*
                 * <CollectionType>
                 * <RowType>
                 *      <Property Name="PersonID" Type="int" Nullable="false" />
                 *      <Property Name="FirstName" Type="nvarchar" MaxLength="50" />
                 *      <Property Name="LastName" Type="nvarchar" MaxLength="50" />
                 *      <Property Name="JobTitle" Type="nvarchar" MaxLength="50" />
                 *      <Property Name="BusinessEntityType" Type="nvarchar" MaxLength="50" />
                 * </RowType>
                 * </CollectionType>
                 */

                // returnParameterInfo.ParameterType is IQueryable<T>.
                var storeReturnParameterClrType        = methodInfo.ReturnParameter.ParameterType.GetGenericArguments().Single();
                var modelReturnParameterStructuralType = GetModelStructualType(model, storeReturnParameterClrType, methodInfo);
                var modelReturnParameterComplexType    = modelReturnParameterStructuralType as ComplexType;

                RowType storeReturnParameterRowType = null;
                if (modelReturnParameterComplexType != null)
                {
                    storeReturnParameterRowType = RowType.Create(
                        modelReturnParameterComplexType.Properties.Select(property =>
                                                                          EdmProperty.Create(property.Name, model.ProviderManifest.GetStoreType(property.TypeUsage))), null);
                }
                else
                {
                    var modelReturnParameterEntityType = modelReturnParameterStructuralType as EntityType;
                    if (modelReturnParameterEntityType != null)
                    {
                        storeReturnParameterRowType = RowType.Create(
                            modelReturnParameterEntityType.Properties.Select(property => CloneEdmProperty(property)), null);
                    }
                    else
                    {
                        throw new NotSupportedException(string.Format("Structural type {0} of method {1} cannot be converted to RowType.", modelReturnParameterStructuralType.FullName, methodInfo.Name));
                    }
                }

                return(new[]
                {
                    FunctionParameter.Create(
                        "ReturnType",
                        storeReturnParameterRowType.GetCollectionType(), // Collection of RowType.
                        ParameterMode.ReturnValue)
                });
            }

            //if (functionAttribute.Type == FunctionType.NonComposableScalarValuedFunction)
            //{
            //	// Non-composable scalar-valued function.
            //	return new FunctionParameter[0];
            //}

            // Composable scalar-valued/Aggregate/Built in/Niladic function.
            // <Function Name="ufnGetProductListPrice" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="true" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo"
            //    ReturnType ="money">
            var storeReturnParameterPrimitiveType = GetStoreParameterPrimitiveType(model, methodInfo, methodInfo.ReturnParameter, functionAttribute);

            return(new[]
            {
                FunctionParameter.Create("ReturnType", storeReturnParameterPrimitiveType, ParameterMode.ReturnValue)
            });
        }