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); }
public void Crate_creates_store_function_for_primitive_function_import() { var model = new DbModelBuilder() .Build(new DbProviderInfo("System.Data.SqlClient", "2012")); var functionDescriptor = new FunctionDescriptor( "f", new[] { new ParameterDescriptor( "p1", PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String), null, false), }, new EdmType[] { PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int64) }, "ResultCol", "dbo", StoreFunctionKind.TableValuedFunction, isBuiltIn: null); var storeFunction = new StoreFunctionBuilder(model, "docs", "ns").Create(functionDescriptor); Assert.Equal( BuiltInTypeKind.CollectionType, storeFunction.ReturnParameter.TypeUsage.EdmType.BuiltInTypeKind); var collectionItemType = (RowType)((CollectionType)storeFunction.ReturnParameter.TypeUsage.EdmType).TypeUsage.EdmType; Assert.Equal(1, collectionItemType.Properties.Count); Assert.Equal("ResultCol", collectionItemType.Properties[0].Name); Assert.Equal("bigint", collectionItemType.Properties[0].TypeUsage.EdmType.Name); 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.True(storeFunction.IsComposableAttribute); }
public void StoreFunctionBuilder_uses_default_namespace_if_no_entities() { var model = new DbModelBuilder() .Build(new DbProviderInfo("System.Data.SqlClient", "2012")); var functionDescriptor = new FunctionDescriptor( "f", new[] { new ParameterDescriptor("p1", PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String), null, false) }, new EdmType[] { PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int64) }, "ResultCol", "dbo", StoreFunctionKind.TableValuedFunction, isBuiltIn: null); var storeFunction = new StoreFunctionBuilder(model, "docs").Create(functionDescriptor); Assert.Equal("CodeFirstDatabaseSchema", storeFunction.NamespaceName); }
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); }
public void Can_specify_store_type_for_parameters() { var model = new DbModelBuilder() .Build(new DbProviderInfo("System.Data.SqlClient", "2012")); var functionDescriptor = new FunctionDescriptor( "f", new[] { new ParameterDescriptor( "p1", PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String), "xml", true), }, new EdmType[] { PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int64) }, "ResultCol", "dbo", StoreFunctionKind.StoredProcedure, isBuiltIn: null); var storeFunction = new StoreFunctionBuilder(model, "docs", "ns").Create(functionDescriptor); Assert.Equal(1, storeFunction.Parameters.Count); Assert.Equal("p1", storeFunction.Parameters[0].Name); Assert.Equal("xml", storeFunction.Parameters[0].TypeName); }
public void Crate_creates_store_function_for_enum_type_function_import() { var model = new DbModelBuilder() .Build(new DbProviderInfo("System.Data.SqlClient", "2012")); var enumTypeCtor = typeof(EnumType).GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance).Single(c => c.GetParameters().Count() == 5); var enumType = (EnumType)enumTypeCtor.Invoke(BindingFlags.NonPublic | BindingFlags.Instance, null, new object[] { "TestEnumType", "Model", PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32), false, DataSpace.CSpace }, CultureInfo.InvariantCulture); var functionDescriptor = new FunctionDescriptor( "f", new[] { new ParameterDescriptor("p1", enumType, null, false) }, new EdmType[] { enumType }, "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); var collectionItemType = (RowType)((CollectionType)storeFunction.ReturnParameter.TypeUsage.EdmType).TypeUsage.EdmType; Assert.Single(collectionItemType.Properties); Assert.Equal("ResultCol", collectionItemType.Properties[0].Name); Assert.Equal("int", collectionItemType.Properties[0].TypeUsage.EdmType.Name); Assert.Single(storeFunction.Parameters); Assert.Equal("p1", storeFunction.Parameters[0].Name); Assert.Equal("int", storeFunction.Parameters[0].TypeName); Assert.Equal(ParameterMode.In, storeFunction.Parameters[0].Mode); Assert.True(storeFunction.IsComposableAttribute); }
public void Apply(EntityContainer item, DbModel model) { var functionDescriptors = new FunctionDiscovery(model, _methodClassType).FindFunctions(); var storeFunctionBuilder = new StoreFunctionBuilder(model, _defaultSchema); foreach (var functionDescriptor in functionDescriptors) { var storeFunctionDefinition = storeFunctionBuilder.Create(functionDescriptor); model.StoreModel.AddItem(storeFunctionDefinition); if (functionDescriptor.StoreFunctionKind != StoreFunctionKind.ScalarUserDefinedFunction) { var functionImportDefinition = CreateFunctionImport(model, functionDescriptor); model.ConceptualModel.Container.AddFunctionImport(functionImportDefinition); if (functionImportDefinition.IsComposableAttribute) { model.ConceptualToStoreMapping.AddFunctionImportMapping( new FunctionImportMappingComposable( functionImportDefinition, storeFunctionDefinition, new FunctionImportResultMapping(), model.ConceptualToStoreMapping)); } else { model.ConceptualToStoreMapping.AddFunctionImportMapping( new FunctionImportMappingNonComposable( functionImportDefinition, storeFunctionDefinition, new FunctionImportResultMapping[0], model.ConceptualToStoreMapping)); } } } // TODO: model defined functions? }
public void Crate_can_create_out_params() { var model = new DbModelBuilder() .Build(new DbProviderInfo("System.Data.SqlClient", "2012")); var functionDescriptor = new FunctionDescriptor( "f", new[] { new ParameterDescriptor( "p1", PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String), null, true), }, new EdmType[] { PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int64) }, "ResultCol", "dbo", StoreFunctionKind.StoredProcedure, isBuiltIn: null); var storeFunction = new StoreFunctionBuilder(model, "docs", "ns").Create(functionDescriptor); Assert.Equal(1, storeFunction.Parameters.Count); Assert.Equal("p1", storeFunction.Parameters[0].Name); Assert.Equal("nvarchar(max)", storeFunction.Parameters[0].TypeName); Assert.Equal(ParameterMode.InOut, storeFunction.Parameters[0].Mode); Assert.False(storeFunction.IsComposableAttribute); }
public void Apply(EntityContainer item, DbModel model) { var functionDescriptors = new FunctionDiscovery(model, _methodClassType).FindFunctions(); var storeFunctionBuilder = new StoreFunctionBuilder(model, _defaultSchema); foreach (var functionDescriptor in functionDescriptors) { var storeFunctionDefinition = storeFunctionBuilder.Create(functionDescriptor); model.StoreModel.AddItem(storeFunctionDefinition); if (functionDescriptor.StoreFunctionKind != StoreFunctionKind.ScalarUserDefinedFunction) { var functionImportDefinition = CreateFunctionImport(model, functionDescriptor); model.ConceptualModel.Container.AddFunctionImport(functionImportDefinition); List <FunctionImportResultMapping> resultMappings = new List <FunctionImportResultMapping>(); if (functionDescriptor.ReturnTypes.All(t => t is EntityType || t is ComplexType)) { foreach (EdmType returnType in functionDescriptor.ReturnTypes) { FunctionImportStructuralTypeMapping typeMapping; if (returnType is EntityType) { var entityType = (EntityType)returnType; var returnTypePropertyMappings = new Collection <FunctionImportReturnTypePropertyMapping>(); foreach (var propertyMapping in model.GetEntityTypePropertyMappings(entityType).OfType <ScalarPropertyMapping>()) { returnTypePropertyMappings.Add(new FunctionImportReturnTypeScalarPropertyMapping(propertyMapping.Property.Name, propertyMapping.Column.Name)); } typeMapping = new FunctionImportEntityTypeMapping( Enumerable.Empty <EntityType>(), new[] { entityType }, returnTypePropertyMappings, Enumerable.Empty <FunctionImportEntityTypeMappingCondition>()); } else // ComplexType { var complexType = (ComplexType)returnType; var returnTypePropertyMappings = new Collection <FunctionImportReturnTypePropertyMapping>(); foreach (var property in complexType.Properties) { returnTypePropertyMappings.Add(new FunctionImportReturnTypeScalarPropertyMapping(property.Name, property.Name)); } typeMapping = new FunctionImportComplexTypeMapping(complexType, returnTypePropertyMappings); } FunctionImportResultMapping resultMapping = new FunctionImportResultMapping(); resultMappings.Add(resultMapping); resultMapping.AddTypeMapping(typeMapping); } } if (functionImportDefinition.IsComposableAttribute) { model.ConceptualToStoreMapping.AddFunctionImportMapping( new FunctionImportMappingComposable( functionImportDefinition, storeFunctionDefinition, resultMappings.FirstOrDefault() ?? new FunctionImportResultMapping(), model.ConceptualToStoreMapping)); } else { // HACK: Currently, FunctionImportMappingNonComposable ctor does not support code-first construction because // it depends on EdmItemCollection being available from StorageMappingItemCollection. Code-first does // not create a StorageMappingItemCollection and, as a result, this ctor will throw a null reference // exception if any result mappings are passed to it in code-first context. This must be resolved in // EF itself. Until then, _only composable functions can support custom named column mappings_. Once // this issue is resolved in EF then the commented code should replace the current "empty array" // resultMapping parameter to enable custom mappings for non-composable functions as well: model.ConceptualToStoreMapping.AddFunctionImportMapping( new FunctionImportMappingNonComposable( functionImportDefinition, storeFunctionDefinition, // resultMappings.Any() ? resultMappings.ToArray() : new FunctionImportResultMapping[0], new FunctionImportResultMapping[0], model.ConceptualToStoreMapping)); } } } // TODO: model defined functions? }