// effects: try to find setter expression for the given member // requires: command tree must be an insert or update tree (since other DML trees hnabve private static bool TryGetSetterExpression( DbModificationCommandTree tree, EdmMember member, ModificationOperator op, out DbSetClause setter) { Debug.Assert(op == ModificationOperator.Insert || op == ModificationOperator.Update, "only inserts and updates have setters"); IEnumerable <DbModificationClause> clauses; if (ModificationOperator.Insert == op) { clauses = ((DbInsertCommandTree)tree).SetClauses; } else { clauses = ((DbUpdateCommandTree)tree).SetClauses; } foreach (DbSetClause setClause in clauses) { // check if this is the correct setter if (((DbPropertyExpression)setClause.Property).Property.EdmEquals(member)) { setter = setClause; return(true); } } // no match found setter = null; return(false); }
// effects: try to find setter expression for the given member // requires: command tree must be an insert or update tree (since other DML trees hnabve private static bool TryGetSetterExpression( DbModificationCommandTree tree, EdmMember member, ModificationOperator op, out DbSetClause setter) { Debug.Assert(op == ModificationOperator.Insert || op == ModificationOperator.Update, "only inserts and updates have setters"); IEnumerable<DbModificationClause> clauses; if (ModificationOperator.Insert == op) { clauses = ((DbInsertCommandTree)tree).SetClauses; } else { clauses = ((DbUpdateCommandTree)tree).SetClauses; } foreach (DbSetClause setClause in clauses) { // check if this is the correct setter if (((DbPropertyExpression)setClause.Property).Property.EdmEquals(member)) { setter = setClause; return true; } } // no match found setter = null; return false; }
internal DynamicUpdateCommand( TableChangeProcessor processor, UpdateTranslator translator, ModificationOperator modificationOperator, PropagatorResult originalValues, PropagatorResult currentValues, DbModificationCommandTree tree, Dictionary <int, string> outputIdentifiers) : base(translator, originalValues, currentValues) { this._processor = processor; this._operator = modificationOperator; this._modificationCommandTree = tree; this._outputIdentifiers = outputIdentifiers; if (ModificationOperator.Insert != modificationOperator && modificationOperator != ModificationOperator.Update) { return; } this._inputIdentifiers = new List <KeyValuePair <int, DbSetClause> >(2); foreach (KeyValuePair <EdmMember, PropagatorResult> pairEnumeration in Helper.PairEnumerations <EdmMember, PropagatorResult>(TypeHelpers.GetAllStructuralMembers((EdmType)this.CurrentValues.StructuralType), (IEnumerable <PropagatorResult>) this.CurrentValues.GetMemberValues())) { int identifier = pairEnumeration.Value.Identifier; DbSetClause setter; if (-1 != identifier && DynamicUpdateCommand.TryGetSetterExpression(tree, pairEnumeration.Key, modificationOperator, out setter)) { foreach (int principal in translator.KeyManager.GetPrincipals(identifier)) { this._inputIdentifiers.Add(new KeyValuePair <int, DbSetClause>(principal, setter)); } } } }
internal DynamicUpdateCommand(TableChangeProcessor processor, UpdateTranslator translator, ModificationOperator op, PropagatorResult originalValues, PropagatorResult currentValues, DbModificationCommandTree tree, Dictionary<int, string> outputIdentifiers) : base(originalValues, currentValues) { m_processor = EntityUtil.CheckArgumentNull(processor, "processor"); m_operator = op; m_modificationCommandTree = EntityUtil.CheckArgumentNull(tree, "commandTree"); m_outputIdentifiers = outputIdentifiers; // may be null (not all commands have output identifiers) // initialize identifier information (supports lateral propagation of server gen values) if (ModificationOperator.Insert == op || ModificationOperator.Update == op) { const int capacity = 2; // "average" number of identifiers per row m_inputIdentifiers = new List<KeyValuePair<int ,DbSetClause>>(capacity); foreach (KeyValuePair<EdmMember, PropagatorResult> member in Helper.PairEnumerations(TypeHelpers.GetAllStructuralMembers(this.CurrentValues.StructuralType), this.CurrentValues.GetMemberValues())) { DbSetClause setter; int identifier = member.Value.Identifier; if (PropagatorResult.NullIdentifier != identifier && TryGetSetterExpression(tree, member.Key, op, out setter)) // can find corresponding setter { foreach (int principal in translator.KeyManager.GetPrincipals(identifier)) { m_inputIdentifiers.Add(new KeyValuePair<int, DbSetClause>(principal, setter)); } } } } }
internal DynamicUpdateCommand(TableChangeProcessor processor, UpdateTranslator translator, ModificationOperator op, PropagatorResult originalValues, PropagatorResult currentValues, DbModificationCommandTree tree, Dictionary <int, string> outputIdentifiers) : base(originalValues, currentValues) { m_processor = EntityUtil.CheckArgumentNull(processor, "processor"); m_operator = op; m_modificationCommandTree = EntityUtil.CheckArgumentNull(tree, "commandTree"); m_outputIdentifiers = outputIdentifiers; // may be null (not all commands have output identifiers) // initialize identifier information (supports lateral propagation of server gen values) if (ModificationOperator.Insert == op || ModificationOperator.Update == op) { const int capacity = 2; // "average" number of identifiers per row m_inputIdentifiers = new List <KeyValuePair <int, DbSetClause> >(capacity); foreach (KeyValuePair <EdmMember, PropagatorResult> member in Helper.PairEnumerations(TypeHelpers.GetAllStructuralMembers(this.CurrentValues.StructuralType), this.CurrentValues.GetMemberValues())) { DbSetClause setter; int identifier = member.Value.Identifier; if (PropagatorResult.NullIdentifier != identifier && TryGetSetterExpression(tree, member.Key, op, out setter)) // can find corresponding setter { foreach (int principal in translator.KeyManager.GetPrincipals(identifier)) { m_inputIdentifiers.Add(new KeyValuePair <int, DbSetClause>(principal, setter)); } } } } }
private ModificationFunctionMapping GenerateFunctionMapping( ModificationOperator modificationOperator, EntitySetBase entitySetBase, EntityTypeBase entityTypeBase, DbDatabaseMapping databaseMapping, IEnumerable <EdmProperty> parameterProperties, IEnumerable <Tuple <ModificationFunctionMemberPath, EdmProperty> > iaFkProperties, IList <ColumnMappingBuilder> columnMappings, IEnumerable <EdmProperty> resultProperties = null, string functionNamePrefix = null) { bool useOriginalValues = modificationOperator == ModificationOperator.Delete; FunctionParameterMappingGenerator mappingGenerator = new FunctionParameterMappingGenerator(this._providerManifest); List <ModificationFunctionParameterBinding> list1 = mappingGenerator.Generate(modificationOperator != ModificationOperator.Insert || !ModificationFunctionMappingGenerator.IsTableSplitDependent(entityTypeBase, databaseMapping) ? modificationOperator : ModificationOperator.Update, parameterProperties, columnMappings, (IList <EdmProperty>) new List <EdmProperty>(), useOriginalValues).Concat <ModificationFunctionParameterBinding>(mappingGenerator.Generate(iaFkProperties, useOriginalValues)).ToList <ModificationFunctionParameterBinding>(); List <FunctionParameter> list2 = list1.Select <ModificationFunctionParameterBinding, FunctionParameter>((Func <ModificationFunctionParameterBinding, FunctionParameter>)(b => b.Parameter)).ToList <FunctionParameter>(); ModificationFunctionMappingGenerator.UniquifyParameterNames((IList <FunctionParameter>)list2); EdmFunctionPayload functionPayload = new EdmFunctionPayload() { ReturnParameters = (IList <FunctionParameter>) new FunctionParameter[0], Parameters = (IList <FunctionParameter>)list2.ToArray(), IsComposable = new bool?(false) }; EdmFunction function = databaseMapping.Database.AddFunction((functionNamePrefix ?? entityTypeBase.Name) + "_" + modificationOperator.ToString(), functionPayload); return(new ModificationFunctionMapping(entitySetBase, entityTypeBase, function, (IEnumerable <ModificationFunctionParameterBinding>)list1, (FunctionParameter)null, resultProperties != null ? resultProperties.Select <EdmProperty, ModificationFunctionResultBinding>((Func <EdmProperty, ModificationFunctionResultBinding>)(p => new ModificationFunctionResultBinding(columnMappings.First <ColumnMappingBuilder>((Func <ColumnMappingBuilder, bool>)(cm => cm.PropertyPath.SequenceEqual <EdmProperty>((IEnumerable <EdmProperty>) new EdmProperty[1] { p }))).ColumnProperty.Name, p))) : (IEnumerable <ModificationFunctionResultBinding>)null)); }
public IEnumerable <ModificationFunctionParameterBinding> Generate( ModificationOperator modificationOperator, IEnumerable <EdmProperty> properties, IList <ColumnMappingBuilder> columnMappings, IList <EdmProperty> propertyPath, bool useOriginalValues = false) { foreach (EdmProperty property1 in properties) { EdmProperty property = property1; if (property.IsComplexType && propertyPath.Any <EdmProperty>((Func <EdmProperty, bool>)(p => { if (p.IsComplexType) { return(p.ComplexType == property.ComplexType); } return(false); }))) { throw Error.CircularComplexTypeHierarchy(); } propertyPath.Add(property); if (property.IsComplexType) { foreach (ModificationFunctionParameterBinding parameterBinding in this.Generate(modificationOperator, (IEnumerable <EdmProperty>)property.ComplexType.Properties, columnMappings, propertyPath, useOriginalValues)) { yield return(parameterBinding); } } else { StoreGeneratedPattern?generatedPattern1 = property.GetStoreGeneratedPattern(); if ((generatedPattern1.GetValueOrDefault() != StoreGeneratedPattern.Identity ? 1 : (!generatedPattern1.HasValue ? 1 : 0)) != 0 || modificationOperator != ModificationOperator.Insert) { EdmProperty columnProperty = columnMappings.First <ColumnMappingBuilder>((Func <ColumnMappingBuilder, bool>)(cm => cm.PropertyPath.SequenceEqual <EdmProperty>((IEnumerable <EdmProperty>)propertyPath))).ColumnProperty; StoreGeneratedPattern?generatedPattern2 = property.GetStoreGeneratedPattern(); if ((generatedPattern2.GetValueOrDefault() != StoreGeneratedPattern.Computed ? 1 : (!generatedPattern2.HasValue ? 1 : 0)) != 0 && (modificationOperator != ModificationOperator.Delete || property.IsKeyMember)) { yield return(new ModificationFunctionParameterBinding(new FunctionParameter(columnProperty.Name, columnProperty.TypeUsage, ParameterMode.In), new ModificationFunctionMemberPath((IEnumerable <EdmMember>)propertyPath, (AssociationSet)null), !useOriginalValues)); } if (modificationOperator != ModificationOperator.Insert && property.ConcurrencyMode == ConcurrencyMode.Fixed) { yield return(new ModificationFunctionParameterBinding(new FunctionParameter(columnProperty.Name + "_Original", columnProperty.TypeUsage, ParameterMode.In), new ModificationFunctionMemberPath((IEnumerable <EdmMember>)propertyPath, (AssociationSet)null), false)); } } } propertyPath.Remove(property); } }
private static bool TryGetSetterExpression( DbModificationCommandTree tree, EdmMember member, ModificationOperator op, out DbSetClause setter) { foreach (DbSetClause dbSetClause in ModificationOperator.Insert != op ? (IEnumerable <DbModificationClause>)((DbUpdateCommandTree)tree).SetClauses : (IEnumerable <DbModificationClause>)((DbInsertCommandTree)tree).SetClauses) { if (((DbPropertyExpression)dbSetClause.Property).Property.EdmEquals((MetadataItem)member)) { setter = dbSetClause; return(true); } } setter = (DbSetClause)null; return(false); }
internal DynamicUpdateCommand( TableChangeProcessor processor, UpdateTranslator translator, ModificationOperator modificationOperator, PropagatorResult originalValues, PropagatorResult currentValues, DbModificationCommandTree tree, Dictionary<int, string> outputIdentifiers) : base(translator, originalValues, currentValues) { Contract.Requires(processor != null); Contract.Requires(translator != null); Contract.Requires(tree != null); _processor = processor; _operator = modificationOperator; _modificationCommandTree = tree; _outputIdentifiers = outputIdentifiers; // may be null (not all commands have output identifiers) // initialize identifier information (supports lateral propagation of server gen values) if (ModificationOperator.Insert == modificationOperator || ModificationOperator.Update == modificationOperator) { const int capacity = 2; // "average" number of identifiers per row _inputIdentifiers = new List<KeyValuePair<int, DbSetClause>>(capacity); foreach (var member in Helper.PairEnumerations( TypeHelpers.GetAllStructuralMembers(CurrentValues.StructuralType), CurrentValues.GetMemberValues())) { DbSetClause setter; var identifier = member.Value.Identifier; if (PropagatorResult.NullIdentifier != identifier && TryGetSetterExpression(tree, member.Key, modificationOperator, out setter)) // can find corresponding setter { foreach (var principal in translator.KeyManager.GetPrincipals(identifier)) { _inputIdentifiers.Add(new KeyValuePair<int, DbSetClause>(principal, setter)); } } } } }
public IEnumerable <ModificationFunctionParameterBinding> Generate( ModificationOperator modificationOperator, IEnumerable <EdmProperty> properties, IList <ColumnMappingBuilder> columnMappings, IList <EdmProperty> propertyPath, bool useOriginalValues = false) { DebugCheck.NotNull(properties); DebugCheck.NotNull(columnMappings); DebugCheck.NotNull(propertyPath); foreach (var property in properties) { if (property.IsComplexType && propertyPath.Any( p => p.IsComplexType && (p.ComplexType == property.ComplexType))) { throw Error.CircularComplexTypeHierarchy(); } propertyPath.Add(property); if (property.IsComplexType) { foreach (var parameterBinding in Generate(modificationOperator, property.ComplexType.Properties, columnMappings, propertyPath, useOriginalValues)) { yield return(parameterBinding); } } else { if ((property.GetStoreGeneratedPattern() != StoreGeneratedPattern.Identity) || (modificationOperator != ModificationOperator.Insert)) { var columnProperty = columnMappings.First(cm => cm.PropertyPath.SequenceEqual(propertyPath)).ColumnProperty; if ((property.GetStoreGeneratedPattern() != StoreGeneratedPattern.Computed) && ((modificationOperator != ModificationOperator.Delete) || property.IsKeyMember)) { yield return (new ModificationFunctionParameterBinding( new FunctionParameter(columnProperty.Name, columnProperty.TypeUsage, ParameterMode.In), new ModificationFunctionMemberPath(propertyPath, null), isCurrent: !useOriginalValues)); } if (modificationOperator != ModificationOperator.Insert && property.ConcurrencyMode == ConcurrencyMode.Fixed) { yield return (new ModificationFunctionParameterBinding( new FunctionParameter(columnProperty.Name + "_Original", columnProperty.TypeUsage, ParameterMode.In), new ModificationFunctionMemberPath(propertyPath, null), isCurrent: false)); } } } propertyPath.Remove(property); } }
private ModificationFunctionMapping GenerateFunctionMapping( ModificationOperator modificationOperator, EntitySetBase entitySetBase, EntityTypeBase entityTypeBase, DbDatabaseMapping databaseMapping, IEnumerable <EdmProperty> parameterProperties, IEnumerable <Tuple <ModificationFunctionMemberPath, EdmProperty> > iaFkProperties, IList <ColumnMappingBuilder> columnMappings, IEnumerable <EdmProperty> resultProperties = null, string functionNamePrefix = null) { DebugCheck.NotNull(entitySetBase); DebugCheck.NotNull(entityTypeBase); DebugCheck.NotNull(databaseMapping); DebugCheck.NotNull(parameterProperties); DebugCheck.NotNull(iaFkProperties); DebugCheck.NotNull(columnMappings); var useOriginalValues = modificationOperator == ModificationOperator.Delete; var parameterMappingGenerator = new FunctionParameterMappingGenerator(_providerManifest); var parameterBindings = parameterMappingGenerator .Generate( modificationOperator, parameterProperties, columnMappings, new List <EdmProperty>(), useOriginalValues) .Concat( parameterMappingGenerator .Generate(iaFkProperties, useOriginalValues)) .ToList(); var parameters = parameterBindings.Select(b => b.Parameter).ToList(); UniquifyParameterNames(parameters); var functionPayload = new EdmFunctionPayload { ReturnParameters = new FunctionParameter[0], Parameters = parameters.ToArray(), IsComposable = false }; var function = databaseMapping.Database .AddFunction( (functionNamePrefix ?? entityTypeBase.Name) + "_" + modificationOperator.ToString(), functionPayload); var functionMapping = new ModificationFunctionMapping( entitySetBase, entityTypeBase, function, parameterBindings, null, resultProperties != null ? resultProperties.Select( p => new ModificationFunctionResultBinding( columnMappings.First(cm => cm.PropertyPath.SequenceEqual(new[] { p })).ColumnProperty.Name, p)) : null); return(functionMapping); }
private ModificationFunctionMapping GenerateFunctionMapping( ModificationOperator modificationOperator, EntitySetBase entitySetBase, EntityTypeBase entityTypeBase, DbDatabaseMapping databaseMapping, IEnumerable<EdmProperty> parameterProperties, IEnumerable<Tuple<ModificationFunctionMemberPath, EdmProperty>> iaFkProperties, IList<ColumnMappingBuilder> columnMappings, IEnumerable<EdmProperty> resultProperties = null, string functionNamePrefix = null) { DebugCheck.NotNull(entitySetBase); DebugCheck.NotNull(entityTypeBase); DebugCheck.NotNull(databaseMapping); DebugCheck.NotNull(parameterProperties); DebugCheck.NotNull(iaFkProperties); DebugCheck.NotNull(columnMappings); var useOriginalValues = modificationOperator == ModificationOperator.Delete; var parameterMappingGenerator = new FunctionParameterMappingGenerator(_providerManifest); var parameterBindings = parameterMappingGenerator .Generate( modificationOperator == ModificationOperator.Insert && IsTableSplitDependent(entityTypeBase, databaseMapping) ? ModificationOperator.Update : modificationOperator, parameterProperties, columnMappings, new List<EdmProperty>(), useOriginalValues) .Concat( parameterMappingGenerator .Generate(iaFkProperties, useOriginalValues)) .ToList(); var parameters = parameterBindings.Select(b => b.Parameter).ToList(); UniquifyParameterNames(parameters); var functionPayload = new EdmFunctionPayload { ReturnParameters = new FunctionParameter[0], Parameters = parameters.ToArray(), IsComposable = false }; var function = databaseMapping.Database .AddFunction( (functionNamePrefix ?? entityTypeBase.Name) + "_" + modificationOperator.ToString(), functionPayload); var functionMapping = new ModificationFunctionMapping( entitySetBase, entityTypeBase, function, parameterBindings, null, resultProperties != null ? resultProperties.Select( p => new ModificationFunctionResultBinding( columnMappings.First(cm => cm.PropertyPath.SequenceEqual(new[] { p })).ColumnProperty.Name, p)) : null); return functionMapping; }
public IEnumerable<ModificationFunctionParameterBinding> Generate( ModificationOperator modificationOperator, IEnumerable<EdmProperty> properties, IList<ColumnMappingBuilder> columnMappings, IList<EdmProperty> propertyPath, bool useOriginalValues = false) { DebugCheck.NotNull(properties); DebugCheck.NotNull(columnMappings); DebugCheck.NotNull(propertyPath); foreach (var property in properties) { if (property.IsComplexType && propertyPath.Any( p => p.IsComplexType && (p.ComplexType == property.ComplexType))) { throw Error.CircularComplexTypeHierarchy(); } propertyPath.Add(property); if (property.IsComplexType) { foreach (var parameterBinding in Generate(modificationOperator, property.ComplexType.Properties, columnMappings, propertyPath, useOriginalValues)) { yield return parameterBinding; } } else { if ((property.GetStoreGeneratedPattern() != StoreGeneratedPattern.Identity) || (modificationOperator != ModificationOperator.Insert)) { var columnProperty = columnMappings.First(cm => cm.PropertyPath.SequenceEqual(propertyPath)).ColumnProperty; if ((property.GetStoreGeneratedPattern() != StoreGeneratedPattern.Computed) && ((modificationOperator != ModificationOperator.Delete) || property.IsKeyMember)) { yield return new ModificationFunctionParameterBinding( new FunctionParameter(columnProperty.Name, columnProperty.TypeUsage, ParameterMode.In), new ModificationFunctionMemberPath(propertyPath, null), isCurrent: !useOriginalValues); } if (modificationOperator != ModificationOperator.Insert && property.ConcurrencyMode == ConcurrencyMode.Fixed) { yield return new ModificationFunctionParameterBinding( new FunctionParameter(columnProperty.Name + "_Original", columnProperty.TypeUsage, ParameterMode.In), new ModificationFunctionMemberPath(propertyPath, null), isCurrent: false); } } } propertyPath.Remove(property); } }
private StorageModificationFunctionMapping GenerateFunctionMapping( ModificationOperator modificationOperator, EntitySetBase entitySetBase, EntityTypeBase entityTypeBase, DbDatabaseMapping databaseMapping, IEnumerable <EdmProperty> parameterProperties, IEnumerable <Tuple <StorageModificationFunctionMemberPath, EdmProperty> > iaFkProperties, IList <ColumnMappingBuilder> columnMappings, IEnumerable <EdmProperty> resultProperties = null) { DebugCheck.NotNull(entitySetBase); DebugCheck.NotNull(entityTypeBase); DebugCheck.NotNull(databaseMapping); DebugCheck.NotNull(parameterProperties); DebugCheck.NotNull(iaFkProperties); DebugCheck.NotNull(columnMappings); var useOriginalValues = modificationOperator == ModificationOperator.Delete; var parameterMappingGenerator = new FunctionParameterMappingGenerator(_providerManifest); var parameterBindings = parameterMappingGenerator .Generate( modificationOperator, parameterProperties, columnMappings, new List <EdmProperty>(), useOriginalValues) .Concat( parameterMappingGenerator .Generate(iaFkProperties, useOriginalValues)) .ToList(); FunctionParameter rowsAffectedParameter = null; var parameters = parameterBindings.Select(b => b.Parameter).ToList(); if (parameterBindings .Any( pb => !pb.IsCurrent && pb.MemberPath.AssociationSetEnd == null && ((EdmProperty)pb.MemberPath.Members.Last()).ConcurrencyMode == ConcurrencyMode.Fixed)) { rowsAffectedParameter = new FunctionParameter( "RowsAffected", _providerManifest.GetStoreType( TypeUsage.CreateDefaultTypeUsage( PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32))), ParameterMode.Out); parameters.Add(rowsAffectedParameter); } UniquifyParameterNames(parameters); var functionPayload = new EdmFunctionPayload { ReturnParameters = new FunctionParameter[0], Parameters = parameters.ToArray(), IsComposable = false }; var function = databaseMapping.Database .AddFunction( entityTypeBase.Name + "_" + modificationOperator.ToString(), functionPayload); var functionMapping = new StorageModificationFunctionMapping( entitySetBase, entityTypeBase, function, parameterBindings, rowsAffectedParameter, resultProperties != null ? resultProperties.Select( p => new StorageModificationFunctionResultBinding( columnMappings.First(cm => cm.PropertyPath.SequenceEqual(new[] { p })).ColumnProperty.Name, p)) : null); return(functionMapping); }
private StorageModificationFunctionMapping GenerateFunctionMapping( ModificationOperator modificationOperator, EntitySetBase entitySetBase, EntityTypeBase entityTypeBase, DbDatabaseMapping databaseMapping, IEnumerable<EdmProperty> parameterProperties, IEnumerable<Tuple<StorageModificationFunctionMemberPath, EdmProperty>> iaFkProperties, IList<ColumnMappingBuilder> columnMappings, IEnumerable<EdmProperty> resultProperties = null) { DebugCheck.NotNull(entitySetBase); DebugCheck.NotNull(entityTypeBase); DebugCheck.NotNull(databaseMapping); DebugCheck.NotNull(parameterProperties); DebugCheck.NotNull(iaFkProperties); DebugCheck.NotNull(columnMappings); var useOriginalValues = modificationOperator == ModificationOperator.Delete; var parameterMappingGenerator = new FunctionParameterMappingGenerator(_providerManifest); var parameterBindings = parameterMappingGenerator .Generate( modificationOperator, parameterProperties, columnMappings, new List<EdmProperty>(), useOriginalValues) .Concat( parameterMappingGenerator .Generate(iaFkProperties, useOriginalValues)) .ToList(); FunctionParameter rowsAffectedParameter = null; var parameters = parameterBindings.Select(b => b.Parameter).ToList(); if (parameterBindings .Any( pb => !pb.IsCurrent && pb.MemberPath.AssociationSetEnd == null && ((EdmProperty)pb.MemberPath.Members.Last()).ConcurrencyMode == ConcurrencyMode.Fixed)) { rowsAffectedParameter = new FunctionParameter( "RowsAffected", _providerManifest.GetStoreType( TypeUsage.CreateDefaultTypeUsage( PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32))), ParameterMode.Out); parameters.Add(rowsAffectedParameter); } UniquifyParameterNames(parameters); var functionPayload = new EdmFunctionPayload { ReturnParameters = new FunctionParameter[0], Parameters = parameters.ToArray(), IsComposable = false }; var function = databaseMapping.Database .AddFunction( entityTypeBase.Name + "_" + modificationOperator.ToString(), functionPayload); var functionMapping = new StorageModificationFunctionMapping( entitySetBase, entityTypeBase, function, parameterBindings, rowsAffectedParameter, resultProperties != null ? resultProperties.Select( p => new StorageModificationFunctionResultBinding( columnMappings.First(cm => cm.PropertyPath.SequenceEqual(new[] { p })).ColumnProperty.Name, p)) : null); return functionMapping; }