Example #1
0
        // 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;
        }
Example #3
0
 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));
                        }
                    }
                }
            }
        }
Example #6
0
        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));
        }
Example #7
0
 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);
     }
 }
Example #8
0
 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));
                        }
                    }
                }
            }
        }
Example #10
0
        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;
        }