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); } }
/// <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) }); }