Beispiel #1
0
        // internal for testing
        internal static EdmProperty GenerateScalarProperty(
            SimpleMappingContext mappingContext, EdmProperty storeProperty, UniqueIdentifierService uniquePropertyNameService)
        {
            Debug.Assert(storeProperty != null, "storeProperty != null");
            Debug.Assert(uniquePropertyNameService != null, "uniquePropertyNameService != null");

            var conceptualPropertyName = CreateModelName(storeProperty.Name, uniquePropertyNameService);

            var conceptualProperty =
                EdmProperty.Create(conceptualPropertyName, storeProperty.TypeUsage.ModelTypeUsage);

            if (storeProperty.StoreGeneratedPattern != StoreGeneratedPattern.None)
            {
                conceptualProperty.SetMetadataProperties(
                    new List <MetadataProperty>
                {
                    CreateAnnotationMetadataProperty(
                        "StoreGeneratedPattern",
                        Enum.GetName(
                            typeof(StoreGeneratedPattern),
                            storeProperty.StoreGeneratedPattern))
                });
            }

            mappingContext.AddMapping(storeProperty, conceptualProperty);

            return(conceptualProperty);
        }
        private EdmType CreateReturnRowType(string propertyName, EdmType edmType)
        {
            if (edmType.BuiltInTypeKind == BuiltInTypeKind.EntityType)
            {
                var propertyToSoreTypeUsage = FindStoreTypeUsages((EntityType)edmType);
                return
                    (RowType.Create(
                         ((EntityType)edmType).Properties.Select(
                             m => EdmProperty.Create(m.Name, propertyToSoreTypeUsage[m])), null));
            }

            if (edmType.BuiltInTypeKind == BuiltInTypeKind.ComplexType)
            {
                return
                    (RowType.Create(
                         ((StructuralType)edmType).Members.Select(
                             m => EdmProperty.Create(m.Name, GetStorePrimitiveTypeUsage(m.TypeUsage))), null));
            }

            if (edmType.BuiltInTypeKind == BuiltInTypeKind.EnumType)
            {
                return(RowType.Create(new[]
                {
                    EdmProperty.Create(propertyName, GetStorePrimitiveTypeUsage(TypeUsage.CreateDefaultTypeUsage(((EnumType)edmType).UnderlyingType)))
                }, null));
            }

            return
                (RowType.Create(
                     new[]
            {
                EdmProperty.Create(propertyName, GetStorePrimitiveTypeUsage(TypeUsage.CreateDefaultTypeUsage(edmType)))
            }, null));
        }
        public void Crate_creates_store_function_for_complex_type_function_import()
        {
            var model = new DbModelBuilder()
                        .Build(new DbProviderInfo("System.Data.SqlClient", "2012"));

            var complexType = ComplexType.Create("CT", "ns", DataSpace.CSpace,
                                                 new[]
            {
                EdmProperty.Create("Street",
                                   TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String))),
                EdmProperty.Create("ZipCode",
                                   TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32))),
            },
                                                 null);

            var functionDescriptor =
                new FunctionDescriptor(
                    "f",
                    new[]
                    { new ParameterDescriptor("p1", PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String), null, false) },
                    new EdmType[] { complexType },
                    "ResultCol",
                    "dbo",
                    StoreFunctionKind.StoredProcedure);

            var storeFunction = new StoreFunctionBuilder(model, "docs", "ns").Create(functionDescriptor);

            Assert.Null(storeFunction.ReturnParameter);

            Assert.Equal(1, storeFunction.Parameters.Count);
            Assert.Equal("p1", storeFunction.Parameters[0].Name);
            Assert.Equal("nvarchar(max)", storeFunction.Parameters[0].TypeName);
            Assert.Equal(ParameterMode.In, storeFunction.Parameters[0].Mode);
            Assert.False(storeFunction.IsComposableAttribute);
        }
Beispiel #4
0
        public EdmProperty Build <T>(string name, Action <EdmProperty> action)
        {
            var property = EdmProperty.Create(name, this.typeUsageFactory.Create <T>());

            action(property);

            return(property);
        }
Beispiel #5
0
        private static EdmType CreateResultType(DbModel model, ResultDescriptor result)
        {
            EdmType edmType = GetSimpleEdmType(model, result.Type);

            if (edmType == null)
            {
                edmType = GetStructuralEdmType(model, result.Type);
            }
            if (edmType == null)
            {
                throw new InvalidOperationException(string.Format("Edm type is not found for result type {0}.", result.Type.FullName));
            }

            switch (edmType.BuiltInTypeKind)
            {
            case BuiltInTypeKind.EntityType:
                var propertyMappings = ((EntityType)edmType).Properties.Join(
                    model.ConceptualToStoreMapping.EntitySetMappings
                    .SelectMany(t => t.EntityTypeMappings)
                    .Where(t => edmType.Yield(e => e.BaseType, (e, b) => b, e => e != null).Contains(t.EntityType))
                    .SelectMany(tm => tm.Fragments.SelectMany(t => t.PropertyMappings))
                    .OfType <ScalarPropertyMapping>(),
                    p => p,
                    pm => pm.Property,
                    (p, pm) => new
                {
                    Property  = p,
                    TypeUsage = TypeUsage.Create(pm.Column.TypeUsage.EdmType, pm.Column.TypeUsage.Facets.Where(f => !new[] { "StoreGeneratedPattern", "ConcurrencyMode" }.Contains(f.Name)))
                });
                return(RowType.Create(propertyMappings.Select(pm => EdmProperty.Create(pm.Property.Name, pm.TypeUsage)), null));

            case BuiltInTypeKind.ComplexType:
                return(RowType.Create(((StructuralType)edmType).Members.Select(m =>
                {
                    string columnName = null;
                    MetadataProperty metadata;
                    //if (!m.MetadataProperties.TryGetValue("Configuration", true, out metadata) || !metadata.Value.TryGetProperty("ColumnName", out columnName))
                    if (m.MetadataProperties.TryGetValue("ClrAttributes", true, out metadata))
                    {
                        var columnAttr = ((IEnumerable)m.MetadataProperties["ClrAttributes"].Value).OfType <ColumnAttribute>().SingleOrDefault();
                        if (columnAttr != null && !string.IsNullOrEmpty(columnAttr.Name))
                        {
                            columnName = columnAttr.Name;
                        }
                    }
                    return EdmProperty.Create(columnName ?? m.Name, model.ProviderManifest.GetStoreType(m.TypeUsage));
                }), null));

            case BuiltInTypeKind.EnumType:
                return(RowType.Create(new[] { EdmProperty.CreateEnum(result.ColumnName, (EnumType)edmType) }, null));

            case BuiltInTypeKind.PrimitiveType:
                return(RowType.Create(new[] { EdmProperty.CreatePrimitive(result.ColumnName, (PrimitiveType)edmType) }, null));

            default:
                throw new NotSupportedException();
            }
        }
Beispiel #6
0
        public EdmProperty BuildBinary(string name, bool isFixedLength)
        {
            var typeUsage = TypeUsage.CreateBinaryTypeUsage(
                PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Binary),
                isFixedLength);

            var property = EdmProperty.Create(
                name,
                typeUsage);

            return(property);
        }
            private static ComplexType CreateComplexType()
            {
                var prop1 = EdmProperty.Create(
                    "Prop1",
                    TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32)));
                var prop2 = EdmProperty.Create(
                    "Prop2",
                    TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String)));

                return
                    (ComplexType.Create("TestComplexType", "Model", DataSpace.CSpace, new[] { prop1, prop2 }, null));
            }
        private static SimpleMappingContext CreateSimpleMappingContext(bool isForeignKey)
        {
            var int32TypeUsage = TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32));
            var storeP1        = new[] { CreateStoreProperty("storeSourceId", "int") };
            var storeP2        = new[] { CreateStoreProperty("storeTargetId", "int") };
            var modelP1        = new[] { EdmProperty.Create("modelSourceId", int32TypeUsage) };
            var modelP2        = new[] { EdmProperty.Create("modelTargetId", int32TypeUsage) };
            var storeET1       = EntityType.Create("storeET1", "N", DataSpace.SSpace, new[] { "storeSourceId" }, storeP1, null);
            var storeET2       = EntityType.Create("storeET2", "N", DataSpace.SSpace, new[] { "storeTargetId" }, storeP2, null);
            var modelET1       = EntityType.Create("modelET1", "N", DataSpace.CSpace, new[] { "modelSourceId" }, modelP1, null);
            var modelET2       = EntityType.Create("modelET2", "N", DataSpace.CSpace, new[] { "modelTargetId" }, modelP2, null);
            var storeES1       = EntitySet.Create("storeES1", null, null, null, storeET1, null);
            var storeES2       = EntitySet.Create("storeES2", null, null, null, storeET2, null);
            var modelES1       = EntitySet.Create("modelES1", null, null, null, modelET1, null);
            var modelES2       = EntitySet.Create("modelES2", null, null, null, modelET2, null);
            var storeEM1       = AssociationEndMember.Create(
                "storeEM1", storeET1.GetReferenceType(), RelationshipMultiplicity.One, OperationAction.None, null);
            var storeEM2 = AssociationEndMember.Create(
                "storeEM2", storeET2.GetReferenceType(), RelationshipMultiplicity.One, OperationAction.None, null);
            var modelEM1 = AssociationEndMember.Create(
                "modelEM1", modelET1.GetReferenceType(), RelationshipMultiplicity.Many, OperationAction.None, null);
            var modelEM2 = AssociationEndMember.Create(
                "modelEM2", modelET2.GetReferenceType(), RelationshipMultiplicity.Many, OperationAction.None, null);
            var storeRC        = new ReferentialConstraint(storeEM1, storeEM2, storeP1, storeP2);
            var modelRC        = new ReferentialConstraint(modelEM1, modelEM2, modelP1, modelP2);
            var storeAT        = AssociationType.Create("storeAT", "N", isForeignKey, DataSpace.SSpace, storeEM1, storeEM2, storeRC, null);
            var modelAT        = AssociationType.Create("modelAT", "N", isForeignKey, DataSpace.CSpace, modelEM1, modelEM2, modelRC, null);
            var storeAS        = AssociationSet.Create("storeAS", storeAT, storeES1, storeES2, null);
            var modelAS        = AssociationSet.Create("modelAS", modelAT, modelES1, modelES2, null);
            var storeContainer = EntityContainer.Create(
                "storeContainer", DataSpace.SSpace, new EntitySetBase[] { storeES1, storeES2, storeAS }, null, null);
            var modelContainer = EntityContainer.Create(
                "modelContainer", DataSpace.CSpace, new EntitySetBase[] { modelES1, modelES2, modelAS }, null, null);

            var mappingContext = new SimpleMappingContext(new EdmModel(DataSpace.SSpace), true);

            mappingContext.AddMapping(storeP1[0], modelP1[0]);
            mappingContext.AddMapping(storeP2[0], modelP2[0]);
            mappingContext.AddMapping(storeET1, modelET1);
            mappingContext.AddMapping(storeET2, modelET2);
            mappingContext.AddMapping(storeES1, modelES1);
            mappingContext.AddMapping(storeES2, modelES2);
            mappingContext.AddMapping(storeEM1, modelEM1);
            mappingContext.AddMapping(storeEM2, modelEM2);
            mappingContext.AddMapping(storeAT, modelAT);
            mappingContext.AddMapping(storeAS, modelAS);
            mappingContext.AddMapping(storeAS.AssociationSetEnds[0], modelAS.AssociationSetEnds[0]);
            mappingContext.AddMapping(storeAS.AssociationSetEnds[1], modelAS.AssociationSetEnds[1]);
            mappingContext.AddMapping(storeContainer, modelContainer);

            return(mappingContext);
        }
        public void Can_create_composable_function_import_with_scalar_collection_result()
        {
            DbProviderManifest providerManifest;
            var containerMapping = GetContainerMapping(out providerManifest);

            var cTypeUsageString = TypeUsage.CreateDefaultTypeUsage(
                PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String));
            var sTypeUsageString = providerManifest.GetStoreType(cTypeUsageString);

            var rowType = RowType.Create(
                new[]
            {
                EdmProperty.Create("C", sTypeUsageString),
            },
                null);

            var functionImport = EdmFunction.Create(
                "F", "N", DataSpace.CSpace,
                new EdmFunctionPayload
            {
                IsComposable     = true,
                ReturnParameters = new[]
                {
                    FunctionParameter.Create("R", cTypeUsageString.EdmType.GetCollectionType(), ParameterMode.ReturnValue)
                }
            },
                null);

            var targetFunction = EdmFunction.Create(
                "SF", "N", DataSpace.SSpace,
                new EdmFunctionPayload
            {
                IsComposable     = true,
                ReturnParameters = new[]
                {
                    FunctionParameter.Create("R", rowType.GetCollectionType(), ParameterMode.ReturnValue)
                }
            },
                null);

            var resultMapping = new FunctionImportResultMapping();

            var functionImportMapping = new FunctionImportMappingComposable(
                functionImport,
                targetFunction,
                resultMapping,
                containerMapping);

            Assert.Same(resultMapping, functionImportMapping.ResultMapping);
            Assert.Null(functionImportMapping.StructuralTypeMappings);
            Assert.Null(functionImportMapping.TvfKeys);
        }
Beispiel #10
0
        public EdmProperty BuildString(string name, bool isUnicode, bool isFixedLength)
        {
            var typeUsage = TypeUsage.CreateStringTypeUsage(
                PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String),
                isUnicode,
                isFixedLength);

            var property = EdmProperty.Create(
                name,
                typeUsage);

            return(property);
        }
            private static EntityType CreateEntityType()
            {
                var idProperty = EdmProperty.Create(
                    "Id",
                    TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32)));
                var nameProperty = EdmProperty.Create(
                    "Name",
                    TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String)));

                return
                    (EntityType.Create("TestEntityType", "Model", DataSpace.CSpace, new[] { "Id" },
                                       new[] { idProperty, nameProperty }, null));
            }
        public List <EdmMember> GetEdmMembers(DbModel model)
        {
            List <PropertyInfo> properties = this.mType.GetProperties().ToList();
            List <EdmMember>    members    = new List <EdmMember>();

            foreach (PropertyInfo property in properties)
            {
                PrimitiveType primitiveType = PrimitiveType.GetEdmPrimitiveTypes().FirstOrDefault(t => t.ClrEquivalentType == property.PropertyType);
                EdmType       edmType       = model.ProviderManifest.GetStoreType(TypeUsage.CreateDefaultTypeUsage(primitiveType)).EdmType;
                TypeUsage     typeUsage     = TypeUsage.CreateDefaultTypeUsage(edmType);
                EdmProperty   edmProperty   = EdmProperty.Create(property.Name, typeUsage);
                edmProperty.Nullable = false;
                members.Add(edmProperty);
            }
            return(members);
        }
        private static EdmProperty CloneEdmProperty(EdmProperty property)
        {
            var clone = EdmProperty.Create(property.Name, property.TypeUsage);

            clone.CollectionKind        = property.CollectionKind;
            clone.ConcurrencyMode       = property.ConcurrencyMode;
            clone.IsFixedLength         = property.IsFixedLength;
            clone.IsMaxLength           = property.IsMaxLength;
            clone.IsUnicode             = property.IsUnicode;
            clone.MaxLength             = property.MaxLength;
            clone.Precision             = property.Precision;
            clone.Scale                 = property.Scale;
            clone.StoreGeneratedPattern = property.StoreGeneratedPattern;
            clone.SetMetadataProperties(
                property.MetadataProperties
                .Where(metadataProerty => !clone.MetadataProperties.Any(cloneMetadataProperty => cloneMetadataProperty.Name.Equals(metadataProerty.Name, StringComparison.Ordinal))));
            return(clone);
        }
Beispiel #14
0
        public void Crate_creates_store_function_for_complex_type_withEnum_in_TableValuedFunction()
        {
            var model = new DbModelBuilder()
                        .Build(new DbProviderInfo("System.Data.SqlClient", "2012"));

            var enumType = EnumType.Create("TestEnum", "TestNs", PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32), false, new EnumMember[] { EnumMember.Create("foo", 1, null) }, null);

            var complexType = ComplexType.Create("CT", "ns", DataSpace.CSpace,
                                                 new[]
            {
                EdmProperty.Create("Street",
                                   TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String))),
                EdmProperty.Create("ZipCode",
                                   TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32))),
                EdmProperty.Create("MyEnum", TypeUsage.CreateDefaultTypeUsage(enumType))
            },
                                                 null);

            var functionDescriptor =
                new FunctionDescriptor(
                    "f",
                    new[]
                    { new ParameterDescriptor("p1", PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String), null, false) },
                    new EdmType[] { complexType },
                    "ResultCol",
                    "dbo",
                    StoreFunctionKind.TableValuedFunction,
                    isBuiltIn: null,
                    isNiladic: null);

            var storeFunction = new StoreFunctionBuilder(model, "docs", "ns").Create(functionDescriptor);

            Assert.Equal(
                BuiltInTypeKind.CollectionType,
                storeFunction.ReturnParameter.TypeUsage.EdmType.BuiltInTypeKind);

            Assert.Single(storeFunction.Parameters);
            Assert.Equal("p1", storeFunction.Parameters[0].Name);
            Assert.Equal("nvarchar(max)", storeFunction.Parameters[0].TypeName);
            Assert.Equal(ParameterMode.In, storeFunction.Parameters[0].Mode);
            Assert.True(storeFunction.IsComposableAttribute);
        }
        internal static EdmProperty Clone(this EdmProperty property)
        {
            EdmProperty clone = EdmProperty.Create(property.Name, property.TypeUsage);

            clone.CollectionKind        = property.CollectionKind;
            clone.ConcurrencyMode       = property.ConcurrencyMode;
            clone.IsFixedLength         = property.IsFixedLength;
            clone.IsMaxLength           = property.IsMaxLength;
            clone.IsUnicode             = property.IsUnicode;
            clone.MaxLength             = property.MaxLength;
            clone.Precision             = property.Precision;
            clone.Scale                 = property.Scale;
            clone.StoreGeneratedPattern = property.StoreGeneratedPattern;
            clone.SetMetadataProperties(property
                                        .MetadataProperties
                                        .Where(metadataProerty => !clone
                                               .MetadataProperties
                                               .Any(cloneMetadataProperty => cloneMetadataProperty.Name.EqualsOrdinal(metadataProerty.Name))));
            return(clone);
        }
        private RowType CreateRowTypeFromEntityType(EntityType entityType)
        {
            Debug.Assert(entityType != null, "entityType == null");

            var types = Tools.GetTypeHierarchy(entityType);
            var entityTypeMappings =
                _model.ConceptualToStoreMapping.EntitySetMappings
                .SelectMany(s => s.EntityTypeMappings)
                .Where(t => types.Contains(t.EntityType))
                .ToArray();

            List <EdmProperty> rowTypeProperties = new List <EdmProperty>();

            foreach (var property in entityType.Properties)
            {
                foreach (var entityTypeMapping in entityTypeMappings)
                {
                    var propertyMapping =
                        (ScalarPropertyMapping)entityTypeMapping.Fragments.SelectMany(f => f.PropertyMappings)
                        .FirstOrDefault(p => p.Property == property);

                    if (propertyMapping != null)
                    {
                        // we must use the column name and not just the name of the property to support custom column mappings
                        rowTypeProperties.Add(EdmProperty.Create(propertyMapping.Column.Name,
                                                                 TypeUsage.Create(
                                                                     propertyMapping.Column.TypeUsage.EdmType,
                                                                     propertyMapping.Column.TypeUsage.Facets.Where(
                                                                         f => f.Name != "StoreGeneratedPattern" && f.Name != "ConcurrencyMode"))));

                        break;
                    }
                }
            }

            return(RowType.Create(rowTypeProperties, null));
        }
        public void Can_create_composable_function_import_with_entity_type_collection_result()
        {
            DbProviderManifest providerManifest;
            var containerMapping = GetContainerMapping(out providerManifest);

            var cTypeUsageInt = TypeUsage.Create(
                PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32),
                new[]
            {
                Facet.Create(MetadataItem.NullableFacetDescription, false)
            });
            var sTypeUsageInt = TypeUsage.Create(
                providerManifest.GetStoreType(cTypeUsageInt).EdmType,
                new[]
            {
                Facet.Create(MetadataItem.NullableFacetDescription, false)
            });

            var entityType = EntityType.Create(
                "RT", "N", DataSpace.CSpace,
                new[] { "PId" },
                new[]
            {
                EdmProperty.Create("PId", cTypeUsageInt),
                EdmProperty.Create("P", cTypeUsageInt),
            },
                null);


            var rowType = RowType.Create(
                new[]
            {
                EdmProperty.Create("CId", sTypeUsageInt),
                EdmProperty.Create("C", sTypeUsageInt),
            },
                null);

            var functionImport = EdmFunction.Create(
                "F", "N", DataSpace.CSpace,
                new EdmFunctionPayload
            {
                IsComposable     = true,
                ReturnParameters = new[]
                {
                    FunctionParameter.Create("R", entityType.GetCollectionType(), ParameterMode.ReturnValue)
                }
            },
                null);

            var targetFunction = EdmFunction.Create(
                "SF", "N", DataSpace.SSpace,
                new EdmFunctionPayload
            {
                IsComposable     = true,
                ReturnParameters = new[]
                {
                    FunctionParameter.Create("R", rowType.GetCollectionType(), ParameterMode.ReturnValue)
                }
            },
                null);

            var typeMapping = new FunctionImportEntityTypeMapping(
                Enumerable.Empty <EntityType>(),
                new[] { entityType },
                new Collection <FunctionImportReturnTypePropertyMapping>()
            {
                new FunctionImportReturnTypeScalarPropertyMapping("PId", "CId"),
                new FunctionImportReturnTypeScalarPropertyMapping("P", "C"),
            },
                Enumerable.Empty <FunctionImportEntityTypeMappingCondition>());

            var resultMapping = new FunctionImportResultMapping();

            resultMapping.AddTypeMapping(typeMapping);

            var functionImportMapping = new FunctionImportMappingComposable(
                functionImport,
                targetFunction,
                resultMapping,
                containerMapping);

            Assert.Same(resultMapping, functionImportMapping.ResultMapping);
            Assert.Equal(1, functionImportMapping.StructuralTypeMappings.Count);
            Assert.Equal(1, functionImportMapping.TvfKeys.Length);

            Assert.False(resultMapping.IsReadOnly);
            functionImportMapping.SetReadOnly();
            Assert.True(resultMapping.IsReadOnly);
        }
        public void Build_builds_valid_DbDatabaseMapping_for_functions()
        {
            var rowTypeProperty = CreateStoreProperty("p1", "int");

            var complexTypeProperty =
                EdmProperty.Create(
                    "p2",
                    TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32)));

            var functionImportReturnComplexType =
                ComplexType.Create(
                    "CT",
                    "entityModel",
                    DataSpace.CSpace,
                    new[] { complexTypeProperty }, null);

            var storeFunction = EdmFunction.Create(
                "f_s",
                "storeModel",
                DataSpace.SSpace,
                new EdmFunctionPayload
            {
                IsComposable     = true,
                IsFunctionImport = false,
                ReturnParameters =
                    new[]
                {
                    FunctionParameter.Create(
                        "ReturnType",
                        RowType.Create(new[] { rowTypeProperty }, null).GetCollectionType(),
                        ParameterMode.ReturnValue)
                }
            },
                null);

            var functionImport =
                EdmFunction.Create(
                    "f_c",
                    "entityModel",
                    DataSpace.CSpace,
                    new EdmFunctionPayload
            {
                IsComposable     = true,
                IsFunctionImport = true,
                ReturnParameters =
                    new[]
                {
                    FunctionParameter.Create(
                        "ReturnType",
                        functionImportReturnComplexType.GetCollectionType(),
                        ParameterMode.ReturnValue)
                }
            },
                    null);

            var modelContainer = EntityContainer.Create("C_C", DataSpace.CSpace, new EntitySet[0], new[] { functionImport }, null);
            var storeContainer = EntityContainer.Create("C_S", DataSpace.SSpace, new EntitySet[0], null, null);

            var storeModel = EdmModel.CreateStoreModel(storeContainer, null, null);

            storeModel.AddItem(storeFunction);

            var mappingContext = new SimpleMappingContext(storeModel, true);

            mappingContext.AddMapping(rowTypeProperty, complexTypeProperty);
            mappingContext.AddMapping(storeFunction, functionImport);
            mappingContext.AddMapping(storeContainer, modelContainer);

            var entityModel = DbDatabaseMappingBuilder.Build(mappingContext).ConceptualModel;

            Assert.NotNull(entityModel);
            Assert.Equal(new[] { "f_c" }, entityModel.Containers.Single().FunctionImports.Select(f => f.Name));
            Assert.Equal(new[] { "CT" }, entityModel.ComplexTypes.Select(t => t.Name));
        }
        public void BuildComposableFunctionMapping_creates_valid_function_mapping()
        {
            var rowTypeProperty = CreateStoreProperty("p1", "int");

            var complexTypeProperty =
                EdmProperty.Create(
                    "p2",
                    TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32)));

            var functionImportReturnComplexType =
                ComplexType.Create(
                    "c",
                    "entityModel",
                    DataSpace.CSpace,
                    new[] { complexTypeProperty }, null);

            var storeFunction = EdmFunction.Create(
                "f_s",
                "storeModel",
                DataSpace.SSpace,
                new EdmFunctionPayload
            {
                IsComposable     = true,
                IsFunctionImport = false,
                ReturnParameters =
                    new[]
                {
                    FunctionParameter.Create(
                        "ReturnType",
                        RowType.Create(new[] { rowTypeProperty }, null).GetCollectionType(),
                        ParameterMode.ReturnValue)
                }
            },
                null);

            var functionImport =
                EdmFunction.Create(
                    "f_c",
                    "entityModel",
                    DataSpace.CSpace,
                    new EdmFunctionPayload
            {
                IsComposable     = true,
                IsFunctionImport = false,
                ReturnParameters =
                    new[]
                {
                    FunctionParameter.Create(
                        "ReturnType",
                        functionImportReturnComplexType.GetCollectionType(),
                        ParameterMode.ReturnValue)
                }
            },
                    null);

            var mappingContext = new SimpleMappingContext(new EdmModel(DataSpace.SSpace), true);

            mappingContext.AddMapping(rowTypeProperty, complexTypeProperty);
            mappingContext.AddMapping(storeFunction, functionImport);

            var functionImportMapping =
                DbDatabaseMappingBuilder.BuildComposableFunctionMapping(storeFunction, mappingContext);

            Assert.NotNull(functionImportMapping);
            Assert.Same(storeFunction, functionImportMapping.TargetFunction);
            Assert.Same(functionImport, functionImportMapping.FunctionImport);

            var structuralTypeMappings = functionImportMapping.StructuralTypeMappings;

            Assert.NotNull(structuralTypeMappings);

            Assert.Same(functionImportReturnComplexType, structuralTypeMappings.Single().Item1);
            Assert.Empty(structuralTypeMappings.Single().Item2);
            Assert.Same(complexTypeProperty, structuralTypeMappings.Single().Item3.Single().Property);
            Assert.Same(rowTypeProperty, ((ScalarPropertyMapping)structuralTypeMappings.Single().Item3.Single()).Column);
        }
        public void BuildAssociationSetMappings_builds_conceptual_association_set_mapping_for_collapsed_store_entity_sets()
        {
            #region Setting up many to many relationship in the SSpace Teacher * -- 1 TeacherStudents 1 -- * Teachers

            var joinStoreEntityType =
                EntityType.Create(
                    "TeacherStudents", "ns.Store", DataSpace.SSpace,
                    new[] { "JoinTeacherId", "JoinStudentId" },
                    new[]
            {
                CreateStoreProperty("JoinTeacherId", "int"),
                CreateStoreProperty("JoinStudentId", "int")
            }, null);

            var joinStoreEntitySet =
                EntitySet.Create("TeacherStudentsSet", "dbo", "TeacherStudentTable", null, joinStoreEntityType, null);

            var storeTeacherEntityType =
                EntityType.Create(
                    "Teacher", "ns.Store", DataSpace.SSpace, new[] { "TeacherId" },
                    new[] { CreateStoreProperty("TeacherId", "int") }, null);
            var storeTeacherEntitySet =
                EntitySet.Create("TeachersSet", "dbo", "Teachers", null, storeTeacherEntityType, null);

            var storeStudentEntityType =
                EntityType.Create(
                    "Student", "ns.Store", DataSpace.SSpace, new[] { "StudentId" },
                    new[] { CreateStoreProperty("StudentId", "int") }, null);
            var storeStudentEntitySet =
                EntitySet.Create("StudentSet", "dbo", "Students", null, storeStudentEntityType, null);

            var storeTeachersEndMember =
                AssociationEndMember.Create(
                    "Teachers", storeTeacherEntityType.GetReferenceType(), RelationshipMultiplicity.Many,
                    OperationAction.None, null);

            var storeTeacherStudentsfromTeachersEndMember =
                AssociationEndMember.Create(
                    "TeacherStudents_fromTeachers", joinStoreEntityType.GetReferenceType(), RelationshipMultiplicity.One,
                    OperationAction.None, null);

            var storeTeacherAssociationType =
                AssociationType.Create(
                    "Teacher_TeacherStudentsAssociationType", "ns.Store", false, DataSpace.SSpace,
                    storeTeachersEndMember, storeTeacherStudentsfromTeachersEndMember,
                    new ReferentialConstraint(
                        storeTeachersEndMember, storeTeacherStudentsfromTeachersEndMember, storeTeacherEntityType.KeyProperties,
                        joinStoreEntityType.KeyProperties.Where(p => p.Name == "JoinTeacherId")),
                    null);

            var storeTeacherAssociationSet =
                AssociationSet.Create(
                    "Teacher_TeacherStudents", storeTeacherAssociationType, storeTeacherEntitySet, joinStoreEntitySet, null);

            var storeStudentsEndMember =
                AssociationEndMember.Create(
                    "Students", storeStudentEntityType.GetReferenceType(), RelationshipMultiplicity.Many,
                    OperationAction.None, null);

            var storeTeacherStudentsfromStudentsEndMember =
                AssociationEndMember.Create(
                    "TeacherStudents_fromStudents", joinStoreEntityType.GetReferenceType(), RelationshipMultiplicity.One,
                    OperationAction.None, null);

            var storeStudentAssociationType =
                AssociationType.Create(
                    "Student_TeacherStudentsAssociationType", "ns.Store", false, DataSpace.SSpace,
                    storeStudentsEndMember,
                    storeTeacherStudentsfromStudentsEndMember,
                    new ReferentialConstraint(
                        storeStudentsEndMember, storeTeacherStudentsfromStudentsEndMember, storeStudentEntityType.KeyProperties,
                        joinStoreEntityType.KeyProperties.Where(p => p.Name == "JoinStudentId")),
                    null);

            var storeStudentAssociationSet =
                AssociationSet.Create(
                    "Student_TeacherStudents", storeStudentAssociationType, storeStudentEntitySet, joinStoreEntitySet, null);

            var collapsedAssociationSet = new CollapsibleEntityAssociationSets(joinStoreEntitySet);
            collapsedAssociationSet.AssociationSets.Add(storeTeacherAssociationSet);
            collapsedAssociationSet.AssociationSets.Add(storeStudentAssociationSet);

            #endregion

            #region Setting up many to many relationship in the CSpace Teacher * -- * Teachers

            var conceptualContainer = EntityContainer.Create("ConceptualContainer", DataSpace.CSpace, null, null, null);

            var edmIntTypeUsage =
                TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32));

            var conceptualTeacherEntityType =
                EntityType.Create(
                    "Teacher", "ns", DataSpace.CSpace, new[] { "TeacherId" },
                    new[] { EdmProperty.Create("TeacherId", edmIntTypeUsage) }, null);

            var conceptualTeacherEntitySet =
                EntitySet.Create("TeachersSet", null, null, null, conceptualTeacherEntityType, null);

            var conceptualStudentEntityType =
                EntityType.Create(
                    "Student", "ns", DataSpace.CSpace, new[] { "StudentId" },
                    new[] { EdmProperty.Create("StudentId", edmIntTypeUsage) }, null);

            var conceptualStudentEntitySet =
                EntitySet.Create("StudentSet", "dbo", "Students", null, conceptualStudentEntityType, null);

            var conceptualTeachersEndMember =
                AssociationEndMember.Create(
                    "TeachersEnd", conceptualTeacherEntityType.GetReferenceType(), RelationshipMultiplicity.Many,
                    OperationAction.None, null);

            var conceptualStudentsEndMember =
                AssociationEndMember.Create(
                    "StudentsEnd", conceptualStudentEntityType.GetReferenceType(), RelationshipMultiplicity.Many,
                    OperationAction.None, null);

            var conceptualAssociationType =
                AssociationType.Create(
                    "TeacherStudentAssociation",
                    "ns.Model",
                    false,
                    DataSpace.CSpace,
                    conceptualTeachersEndMember,
                    conceptualStudentsEndMember,
                    new ReferentialConstraint(
                        conceptualTeachersEndMember, conceptualStudentsEndMember,
                        conceptualTeacherEntityType.KeyProperties, conceptualStudentEntityType.KeyProperties),
                    null);

            var conceptualAssociationSet =
                AssociationSet.Create(
                    "TeacherStudentSet", conceptualAssociationType, conceptualTeacherEntitySet,
                    conceptualStudentEntitySet, null);

            #endregion

            var mappingContext = new SimpleMappingContext(new EdmModel(DataSpace.SSpace), true);
            mappingContext.AddMapping(collapsedAssociationSet, conceptualAssociationSet);
            mappingContext.AddMapping(storeTeachersEndMember, conceptualTeachersEndMember);
            mappingContext.AddMapping(storeStudentsEndMember, conceptualStudentsEndMember);
            mappingContext.AddMapping(
                storeTeacherAssociationSet.AssociationSetEnds.ElementAt(0),
                conceptualAssociationSet.AssociationSetEnds.ElementAt(0));
            mappingContext.AddMapping(
                storeStudentAssociationSet.AssociationSetEnds.ElementAt(0),
                conceptualAssociationSet.AssociationSetEnds.ElementAt(1));
            mappingContext.AddMapping(
                storeStudentEntityType.KeyProperties.Single(), conceptualStudentEntityType.KeyProperties.Single());
            mappingContext.AddMapping(
                storeTeacherEntityType.KeyProperties.Single(), conceptualTeacherEntityType.KeyProperties.Single());

            var storageEntitySetMapping =
                new EntityContainerMapping(conceptualContainer, null, null, false, false);

            var associationSetMapping =
                DbDatabaseMappingBuilder.BuildAssociationSetMappings(storageEntitySetMapping, mappingContext)
                .SingleOrDefault();
            Assert.NotNull(associationSetMapping);

            var mappingFragment = associationSetMapping.TypeMappings.SingleOrDefault();
            Assert.NotNull(mappingFragment);

            var propertyMappings = mappingFragment.MappingFragments.Single().PropertyMappings;
            Assert.Equal(2, propertyMappings.Count);
            Assert.Same(conceptualTeachersEndMember, ((EndPropertyMapping)propertyMappings[0]).AssociationEnd);
            Assert.Same(conceptualStudentsEndMember, ((EndPropertyMapping)propertyMappings[1]).AssociationEnd);

            var scalarPropertyMapping = ((EndPropertyMapping)propertyMappings[0]).PropertyMappings.Single();
            Assert.Same(conceptualTeacherEntityType.KeyMembers.Single(), scalarPropertyMapping.Property);
            Assert.Same(
                joinStoreEntityType.KeyMembers.Single(m => m.Name == "JoinTeacherId"),
                scalarPropertyMapping.Column);

            scalarPropertyMapping = ((EndPropertyMapping)propertyMappings[1]).PropertyMappings.Single();
            Assert.Same(conceptualStudentEntityType.KeyMembers.Single(), scalarPropertyMapping.Property);
            Assert.Same(
                joinStoreEntityType.KeyMembers.Single(m => m.Name == "JoinStudentId"),
                scalarPropertyMapping.Column);
        }
Beispiel #21
0
        private static DbCompiledModel CreateModel(NpgsqlConnection connection)
        {
            var dbModelBuilder = new DbModelBuilder(DbModelBuilderVersion.Latest);

            // Import Sets
            dbModelBuilder.Entity <Blog>();
            dbModelBuilder.Entity <Post>();
            dbModelBuilder.Entity <NoColumnsEntity>();
            dbModelBuilder.Entity <User>();
            dbModelBuilder.Entity <Editor>();
            dbModelBuilder.Entity <Administrator>();

            // Import function
            var dbModel = dbModelBuilder.Build(connection);
            var edmType = PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32);

            var addFunc = EdmFunction.Create(
                "ClrStoredAddFunction",
                "BloggingContext",
                DataSpace.SSpace,
                new EdmFunctionPayload
            {
                ParameterTypeSemantics = ParameterTypeSemantics.AllowImplicitConversion,
                Schema                 = "dbo",
                IsComposable           = true,
                IsNiladic              = false,
                IsBuiltIn              = false,
                IsAggregate            = false,
                IsFromProviderManifest = true,
                StoreFunctionName      = "StoredAddFunction",
                ReturnParameters       = new[]
                {
                    FunctionParameter.Create("ReturnType", edmType, ParameterMode.ReturnValue)
                },
                Parameters = new[]
                {
                    FunctionParameter.Create("Value1", edmType, ParameterMode.In),
                    FunctionParameter.Create("Value2", edmType, ParameterMode.In)
                }
            },
                null);

            dbModel.StoreModel.AddItem(addFunc);

            var echoFunc = EdmFunction.Create(
                "StoredEchoFunction",
                "BloggingContext",
                DataSpace.SSpace,
                new EdmFunctionPayload
            {
                ParameterTypeSemantics = ParameterTypeSemantics.AllowImplicitConversion,
                Schema                 = "dbo",
                IsComposable           = true,
                IsNiladic              = false,
                IsBuiltIn              = false,
                IsAggregate            = false,
                IsFromProviderManifest = true,
                StoreFunctionName      = null, // intentional
                ReturnParameters       = new[]
                {
                    FunctionParameter.Create("ReturnType", edmType, ParameterMode.ReturnValue)
                },
                Parameters = new[]
                {
                    FunctionParameter.Create("Value1", edmType, ParameterMode.In)
                }
            },
                null);

            dbModel.StoreModel.AddItem(echoFunc);

            var stringStoreType    = dbModel.ProviderManifest.GetStoreTypes().First(x => x.ClrEquivalentType == typeof(string));
            var modelBlogStoreType = dbModel.StoreModel.EntityTypes.First(x => x.Name == typeof(Blog).Name);
            var rowType            = RowType.Create(
                modelBlogStoreType.Properties.Select(x =>
            {
                var clone                   = EdmProperty.Create(x.Name, x.TypeUsage);
                clone.CollectionKind        = x.CollectionKind;
                clone.ConcurrencyMode       = x.ConcurrencyMode;
                clone.IsFixedLength         = x.IsFixedLength;
                clone.IsMaxLength           = x.IsMaxLength;
                clone.IsUnicode             = x.IsUnicode;
                clone.MaxLength             = x.MaxLength;
                clone.Precision             = x.Precision;
                clone.Scale                 = x.Scale;
                clone.StoreGeneratedPattern = x.StoreGeneratedPattern;
                clone.SetMetadataProperties(x
                                            .MetadataProperties
                                            .Where(metadataProerty => !clone
                                                   .MetadataProperties
                                                   .Any(cloneMetadataProperty => cloneMetadataProperty.Name.Equals(metadataProerty.Name))));
                return(clone);
            }),
                null);

            var getBlogsFunc = EdmFunction.Create(
                "StoredGetBlogsFunction",
                "BloggingContext",
                DataSpace.SSpace,
                new EdmFunctionPayload
            {
                ParameterTypeSemantics = ParameterTypeSemantics.AllowImplicitConversion,
                Schema            = "dbo",
                IsComposable      = true,
                IsNiladic         = false,
                IsBuiltIn         = false,
                IsAggregate       = false,
                StoreFunctionName = "GetBlogsByName",
                ReturnParameters  = new[]
                {
                    FunctionParameter.Create("ReturnType1", rowType.GetCollectionType(), ParameterMode.ReturnValue)
                },
                Parameters = new[]
                {
                    FunctionParameter.Create("Name", stringStoreType, ParameterMode.In)
                }
            },
                null);

            dbModel.StoreModel.AddItem(getBlogsFunc);

            var         stringPrimitiveType     = PrimitiveType.GetEdmPrimitiveTypes().First(x => x.ClrEquivalentType == typeof(string));
            var         modelBlogConceptualType = dbModel.ConceptualModel.EntityTypes.First(x => x.Name == typeof(Blog).Name);
            EdmFunction getBlogsFuncModel       = EdmFunction.Create(
                "GetBlogsByName",
                dbModel.ConceptualModel.Container.Name,
                DataSpace.CSpace,
                new EdmFunctionPayload
            {
                IsFunctionImport = true,
                IsComposable     = true,
                Parameters       = new[]
                {
                    FunctionParameter.Create("Name", stringPrimitiveType, ParameterMode.In)
                },
                ReturnParameters = new[]
                {
                    FunctionParameter.Create("ReturnType1", modelBlogConceptualType.GetCollectionType(), ParameterMode.ReturnValue)
                },
                EntitySets = new[]
                {
                    dbModel.ConceptualModel.Container.EntitySets.First(x => x.ElementType == modelBlogConceptualType)
                }
            },
                null);

            dbModel.ConceptualModel.Container.AddFunctionImport(getBlogsFuncModel);

            dbModel.ConceptualToStoreMapping.AddFunctionImportMapping(new FunctionImportMappingComposable(
                                                                          getBlogsFuncModel,
                                                                          getBlogsFunc,
                                                                          new FunctionImportResultMapping(),
                                                                          dbModel.ConceptualToStoreMapping));

            var compiledModel = dbModel.Compile();

            return(compiledModel);
        }
        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)
            });
        }
        public void Can_create_composable_function_import_with_entity_type_hierarchy()
        {
            DbProviderManifest providerManifest;
            var containerMapping = GetContainerMapping(out providerManifest);

            var cTypeUsageInt = TypeUsage.Create(
                PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32),
                new[]
            {
                Facet.Create(MetadataItem.NullableFacetDescription, false)
            });
            var sTypeUsageInt = TypeUsage.Create(
                providerManifest.GetStoreType(cTypeUsageInt).EdmType,
                new[]
            {
                Facet.Create(MetadataItem.NullableFacetDescription, false)
            });
            var cTypeUsageString = TypeUsage.CreateDefaultTypeUsage(
                PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String));
            var sTypeUsageString = providerManifest.GetStoreType(cTypeUsageString);

            var itemCollection = containerMapping.StorageMappingItemCollection.EdmItemCollection.GetItems <EntityType>();
            var baseEntityType = itemCollection.Single(et => et.Name == "E");
            var entityType1    = itemCollection.Single(et => et.Name == "E1");
            var entityType2    = itemCollection.Single(et => et.Name == "E2");

            var rowType = RowType.Create(
                new[]
            {
                EdmProperty.Create("CId", sTypeUsageInt),
                EdmProperty.Create("C", sTypeUsageString),
                EdmProperty.Create("C1", sTypeUsageString),
                EdmProperty.Create("C2", sTypeUsageString),
                EdmProperty.Create("CD", sTypeUsageString)
            },
                null);

            var functionImport = EdmFunction.Create(
                "F", "N", DataSpace.CSpace,
                new EdmFunctionPayload
            {
                IsComposable     = true,
                ReturnParameters = new[]
                {
                    FunctionParameter.Create("R", baseEntityType.GetCollectionType(), ParameterMode.ReturnValue)
                }
            },
                null);

            var targetFunction = EdmFunction.Create(
                "SF", "N", DataSpace.SSpace,
                new EdmFunctionPayload
            {
                IsComposable     = true,
                ReturnParameters = new[]
                {
                    FunctionParameter.Create("R", rowType.GetCollectionType(), ParameterMode.ReturnValue)
                }
            },
                null);

            var resultMapping = new FunctionImportResultMapping();

            var typeMapping = new FunctionImportEntityTypeMapping(
                new[] { baseEntityType },
                Enumerable.Empty <EntityType>(),
                new Collection <FunctionImportReturnTypePropertyMapping>()
            {
                new FunctionImportReturnTypeScalarPropertyMapping("Id", "CId"),
                new FunctionImportReturnTypeScalarPropertyMapping("P", "C"),
                new FunctionImportReturnTypeScalarPropertyMapping("Discriminator", "CD"),
            },
                Enumerable.Empty <FunctionImportEntityTypeMappingConditionValue>());

            resultMapping.AddTypeMapping(typeMapping);

            typeMapping = new FunctionImportEntityTypeMapping(
                Enumerable.Empty <EntityType>(),
                new[] { entityType1 },
                new Collection <FunctionImportReturnTypePropertyMapping>()
            {
                new FunctionImportReturnTypeScalarPropertyMapping("P1", "C1"),
            },
                new  []
            {
                new FunctionImportEntityTypeMappingConditionValue("CD", "E1")
            });
            resultMapping.AddTypeMapping(typeMapping);

            typeMapping = new FunctionImportEntityTypeMapping(
                Enumerable.Empty <EntityType>(),
                new[] { entityType2 },
                new Collection <FunctionImportReturnTypePropertyMapping>()
            {
                new FunctionImportReturnTypeScalarPropertyMapping("P2", "C2"),
            },
                new []
            {
                new FunctionImportEntityTypeMappingConditionValue("CD", "E2")
            });
            resultMapping.AddTypeMapping(typeMapping);

            var functionImportMapping = new FunctionImportMappingComposable(
                functionImport,
                targetFunction,
                resultMapping,
                containerMapping);

            Assert.Same(resultMapping, functionImportMapping.ResultMapping);
            Assert.Equal(2, functionImportMapping.StructuralTypeMappings.Count);
            Assert.Equal(1, functionImportMapping.TvfKeys.Length);

            Assert.Equal(typeof(E1).Name, functionImportMapping.StructuralTypeMappings[0].Item1.Name);
            Assert.Equal(1, functionImportMapping.StructuralTypeMappings[0].Item2.Count());
            Assert.Equal(3, functionImportMapping.StructuralTypeMappings[0].Item3.Count());

            Assert.Equal(typeof(E2).Name, functionImportMapping.StructuralTypeMappings[1].Item1.Name);
            Assert.Equal(1, functionImportMapping.StructuralTypeMappings[0].Item2.Count());
            Assert.Equal(3, functionImportMapping.StructuralTypeMappings[0].Item3.Count());
        }
Beispiel #24
0
        private static IList <FunctionParameter> GetStoreReturnParameters(
            this DbModel model, MethodInfo methodInfo, FunctionAttribute functionAttribute)
        {
            ParameterInfo returnParameterInfo = methodInfo.ReturnParameter;

            if (returnParameterInfo == null || returnParameterInfo.ParameterType == typeof(void))
            {
                throw new NotSupportedException($"The return type of {methodInfo.Name} is not supported.");
            }

            ParameterAttribute returnParameterAttribute = returnParameterInfo.GetCustomAttribute <ParameterAttribute>();

            ResultTypeAttribute[] returnTypeAttributes = methodInfo.GetCustomAttributes <ResultTypeAttribute>().ToArray();

            if (functionAttribute.Type == FunctionType.StoredProcedure)
            {
                if (returnParameterAttribute != null)
                {
                    throw new NotSupportedException(
                              $"{nameof(ParameterAttribute)} for return value of method {methodInfo.Name} is not supported.");
                }

                return(new FunctionParameter[0]);
            }

            if (returnTypeAttributes.Any())
            {
                throw new NotSupportedException($"{nameof(ResultTypeAttribute)} for method {methodInfo.Name} is not supported.");
            }

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

                /*
                 * <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>.
                Type           storeReturnParameterClrType        = returnParameterInfo.ParameterType.GetGenericArguments().Single();
                StructuralType modelReturnParameterStructuralType = model.GetModelStructualType(
                    storeReturnParameterClrType, methodInfo);
                ComplexType modelReturnParameterComplexType = modelReturnParameterStructuralType as ComplexType;
                RowType     storeReturnParameterRowType;
                if (modelReturnParameterComplexType != null)
                {
                    storeReturnParameterRowType = RowType.Create(
                        modelReturnParameterComplexType.Properties.Select(property =>
                                                                          EdmProperty.Create(property.Name, model.ProviderManifest.GetStoreType(property.TypeUsage))),
                        null);
                }
                else
                {
                    EntityType modelReturnParameterEntityType = modelReturnParameterStructuralType as EntityType;
                    if (modelReturnParameterEntityType != null)
                    {
                        storeReturnParameterRowType = RowType.Create(
                            modelReturnParameterEntityType.Properties.Select(property =>
                        {
                            var typeUsage     = TypeUsage.Create(model.ProviderManifest.GetStoreType(property.TypeUsage).EdmType, property.TypeUsage.Facets);
                            var result        = EdmProperty.Create(property.Name, typeUsage);
                            var propertyNames = new[] { nameof(EdmProperty.Name), nameof(EdmProperty.TypeUsage), nameof(EdmProperty.MetadataProperties) };
                            result.SetMetadataProperties(property.MetadataProperties.Where(m => !propertyNames.Contains(m.Name)));
                            return(result);
                        }),
                            null);
                        //storeReturnParameterRowType = RowType.Create(
                        //    modelReturnParameterEntityType.Properties.Select(property => property.Clone()),
                        //    null);
                    }
                    else
                    {
                        throw new NotSupportedException($"Structural type {modelReturnParameterStructuralType.FullName} of method {methodInfo.Name} cannot be converted to {nameof(RowType)}.");
                    }
                }

                return(new FunctionParameter[]
                {
                    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">
            PrimitiveType storeReturnParameterPrimitiveType = model.GetStoreParameterPrimitiveType(methodInfo, returnParameterInfo, functionAttribute);

            return(new FunctionParameter[]
            {
                FunctionParameter.Create("ReturnType", storeReturnParameterPrimitiveType, ParameterMode.ReturnValue)
            });
        }
Beispiel #25
0
        public void Can_create_non_composable_function_with_multiple_results()
        {
            DbProviderManifest providerManifest;
            var containerMapping = GetContainerMapping(out providerManifest);

            var cTypeUsageInt = TypeUsage.Create(
                PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32),
                new[]
            {
                Facet.Create(MetadataItem.NullableFacetDescription, false)
            });
            var sTypeUsageInt = TypeUsage.Create(
                providerManifest.GetStoreType(cTypeUsageInt).EdmType,
                new[]
            {
                Facet.Create(MetadataItem.NullableFacetDescription, false)
            });
            var cTypeUsageString = TypeUsage.CreateDefaultTypeUsage(
                PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String));
            var sTypeUsageString = providerManifest.GetStoreType(cTypeUsageString);

            var complexType = ComplexType.Create(
                "RT1", "N", DataSpace.CSpace,
                new[]
            {
                EdmProperty.Create("P1", cTypeUsageInt),
                EdmProperty.Create("P2", cTypeUsageString)
            },
                null);

            var entityType = EntityType.Create(
                "RT2", "N", DataSpace.CSpace,
                new[] { "P3" },
                new[]
            {
                EdmProperty.Create("P3", cTypeUsageInt),
                EdmProperty.Create("P4", cTypeUsageString),
            },
                null);

            var rowType1 = RowType.Create(
                new[]
            {
                EdmProperty.Create("C1", sTypeUsageInt),
                EdmProperty.Create("C2", sTypeUsageString)
            },
                null);

            var rowType2 = RowType.Create(
                new[]
            {
                EdmProperty.Create("C3", sTypeUsageInt),
                EdmProperty.Create("C4", sTypeUsageString)
            },
                null);

            var functionImport = EdmFunction.Create(
                "F", "N", DataSpace.CSpace,
                new EdmFunctionPayload
            {
                IsComposable     = false,
                ReturnParameters = new[]
                {
                    FunctionParameter.Create("R1", complexType.GetCollectionType(), ParameterMode.ReturnValue),
                    FunctionParameter.Create("R2", entityType.GetCollectionType(), ParameterMode.ReturnValue)
                },
                EntitySets = new[]
                {
                    new EntitySet(),
                    new EntitySet()
                }
            },
                null);

            var targetFunction = EdmFunction.Create(
                "SF", "N", DataSpace.SSpace,
                new EdmFunctionPayload
            {
                IsComposable     = false,
                ReturnParameters = new[]
                {
                    FunctionParameter.Create("R1", rowType1.GetCollectionType(), ParameterMode.ReturnValue),
                    FunctionParameter.Create("R2", rowType2.GetCollectionType(), ParameterMode.ReturnValue)
                },
                EntitySets = new []
                {
                    new EntitySet(),
                    new EntitySet()
                }
            },
                null);

            var resultMappings
                = new List <FunctionImportResultMapping>
                {
                new FunctionImportResultMapping(),
                new FunctionImportResultMapping()
                };

            resultMappings[0].AddTypeMapping(new FunctionImportComplexTypeMapping(
                                                 complexType,
                                                 new Collection <FunctionImportReturnTypePropertyMapping>()
            {
                new FunctionImportReturnTypeScalarPropertyMapping("P1", "C1"),
                new FunctionImportReturnTypeScalarPropertyMapping("P2", "C2"),
            }));

            resultMappings[1].AddTypeMapping(new FunctionImportEntityTypeMapping(
                                                 Enumerable.Empty <EntityType>(),
                                                 new [] { entityType },
                                                 new Collection <FunctionImportReturnTypePropertyMapping>()
            {
                new FunctionImportReturnTypeScalarPropertyMapping("P3", "C3"),
                new FunctionImportReturnTypeScalarPropertyMapping("P4", "C4")
            },
                                                 Enumerable.Empty <FunctionImportEntityTypeMappingCondition>()));

            var functionImportMapping = new FunctionImportMappingNonComposable(
                functionImport,
                targetFunction,
                resultMappings,
                containerMapping);

            Assert.Equal(resultMappings.Count, functionImportMapping.ResultMappings.Count);

            functionImportMapping.ResultMappings.Each(m => Assert.False(m.IsReadOnly));
            functionImportMapping.SetReadOnly();
            functionImportMapping.ResultMappings.Each(m => Assert.True(m.IsReadOnly));
        }