Esempio n. 1
0
        /// <summary>
        /// Generates the INSERT INTO statement that will apply the row creation
        /// </summary>
        /// <returns>INSERT INTO statement</returns>
        public override string GetScript()
        {
            // Process all the cells, and generate the values
            List <string> values = new List <string>();

            for (int i = 0; i < AssociatedResultSet.Columns.Length; i++)
            {
                DbColumnWrapper column = AssociatedResultSet.Columns[i];
                CellUpdate      cell   = newCells[i];

                // Skip columns that cannot be updated
                if (!column.IsUpdatable)
                {
                    continue;
                }

                // If we're missing a cell, then we cannot continue
                if (cell == null)
                {
                    throw new InvalidOperationException(SR.EditDataCreateScriptMissingValue);
                }

                // Format the value and add it to the list
                values.Add(SqlScriptFormatter.FormatValue(cell.Value, column));
            }
            string joinedValues = string.Join(", ", values);

            // Get the start clause
            string start = GetTableClause();

            // Put the whole #! together
            return(string.Format(InsertCompleteScript, start, joinedValues));
        }
        /// <summary>
        /// Sets the value of the cell in the associated row. If <paramref name="newValue"/> is
        /// identical to the original value, this will remove the cell update from the row update.
        /// </summary>
        /// <param name="columnId">Ordinal of the columns that will be set</param>
        /// <param name="newValue">String representation of the value the user input</param>
        /// <returns>
        /// The string representation of the new value (after conversion to target object) if the
        /// a change is made. <c>null</c> is returned if the cell is reverted to it's original value.
        /// </returns>
        public override EditUpdateCellResult SetCell(int columnId, string newValue)
        {
            // Validate the value and convert to object
            ValidateColumnIsUpdatable(columnId);
            CellUpdate update = new CellUpdate(AssociatedResultSet.Columns[columnId], newValue);

            // If the value is the same as the old value, we shouldn't make changes
            // NOTE: We must use .Equals in order to ignore object to object comparisons
            if (update.Value.Equals(associatedRow[columnId].RawObject))
            {
                // Remove any pending change and stop processing this (we don't care if we fail to remove something)
                CellUpdate cu;
                cellUpdates.TryRemove(columnId, out cu);
                return(new EditUpdateCellResult
                {
                    IsRowDirty = cellUpdates.Count > 0,
                    Cell = new EditCell(associatedRow[columnId], false)
                });
            }

            // The change is real, so set it
            cellUpdates.AddOrUpdate(columnId, update, (i, cu) => update);
            return(new EditUpdateCellResult
            {
                IsRowDirty = true,
                Cell = update.AsEditCell
            });
        }
Esempio n. 3
0
        /// <summary>
        /// Generates the INSERT INTO statement that will apply the row creation
        /// </summary>
        /// <returns>INSERT INTO statement</returns>
        public override string GetScript()
        {
            // Process the cells and columns
            List <string> inColumns = new List <string>();
            List <string> inValues  = new List <string>();

            for (int i = 0; i < AssociatedObjectMetadata.Columns.Length; i++)
            {
                DbColumnWrapper column = AssociatedResultSet.Columns[i];
                CellUpdate      cell   = newCells[i];

                // Continue if we're not inserting a value for this column
                if (!IsCellValueProvided(column, cell, DefaultValues[i]))
                {
                    continue;
                }

                // Column is provided
                inColumns.Add(AssociatedObjectMetadata.Columns[i].EscapedName);
                inValues.Add(ToSqlScript.FormatValue(cell.AsDbCellValue, column));
            }

            // Build the insert statement
            return(inValues.Count > 0
                ? string.Format(InsertScriptValuesStatement,
                                AssociatedObjectMetadata.EscapedMultipartName,
                                string.Join(", ", inColumns),
                                string.Join(", ", inValues))
                : string.Format(InsertScriptDefaultStatement, AssociatedObjectMetadata.EscapedMultipartName));
        }
Esempio n. 4
0
        /// <summary>
        /// Generates a command that can be executed to insert a new row -- and return the newly
        /// inserted row.
        /// </summary>
        /// <param name="connection">The connection the command should be associated with</param>
        /// <returns>Command to insert the new row</returns>
        public override DbCommand GetCommand(DbConnection connection)
        {
            Validate.IsNotNull(nameof(connection), connection);

            // Process all the columns. Add the column to the output columns, add updateable
            // columns to the input parameters
            List <string> outColumns = new List <string>();
            List <string> inColumns  = new List <string>();
            DbCommand     command    = connection.CreateCommand();

            for (int i = 0; i < AssociatedResultSet.Columns.Length; i++)
            {
                DbColumnWrapper column = AssociatedResultSet.Columns[i];
                CellUpdate      cell   = newCells[i];

                // Add the column to the output
                outColumns.Add($"inserted.{SqlScriptFormatter.FormatIdentifier(column.ColumnName)}");

                // Skip columns that cannot be updated
                if (!column.IsUpdatable)
                {
                    continue;
                }

                // If we're missing a cell, then we cannot continue
                if (cell == null)
                {
                    throw new InvalidOperationException(SR.EditDataCreateScriptMissingValue);
                }

                // Create a parameter for the value and add it to the command
                // Add the parameterization to the list and add it to the command
                string paramName = $"@Value{RowId}{i}";
                inColumns.Add(paramName);
                SqlParameter param = new SqlParameter(paramName, cell.Column.SqlDbType)
                {
                    Value = cell.Value
                };
                command.Parameters.Add(param);
            }
            string joinedInColumns  = string.Join(", ", inColumns);
            string joinedOutColumns = string.Join(", ", outColumns);

            // Get the start clause
            string start = GetTableClause();

            // Put the whole #! together
            command.CommandText = string.Format(InsertCompleteOutput, start, joinedOutColumns, joinedInColumns);
            command.CommandType = CommandType.Text;

            return(command);
        }
        /// <summary>
        /// Sets the value of a cell in the row to be added
        /// </summary>
        /// <param name="columnId">Ordinal of the column to set in the row</param>
        /// <param name="newValue">String representation from the client of the value to add</param>
        /// <returns>
        /// The updated value as a string of the object generated from <paramref name="newValue"/>
        /// </returns>
        public override EditUpdateCellResult SetCell(int columnId, string newValue)
        {
            // Validate the column and the value and convert to object
            ValidateColumnIsUpdatable(columnId);
            CellUpdate update = new CellUpdate(AssociatedResultSet.Columns[columnId], newValue);

            // Add the cell update to the
            newCells[columnId] = update;

            // Put together a result of the change
            return(new EditUpdateCellResult
            {
                IsRowDirty = true,                // Row creates will always be dirty
                Cell = update.AsEditCell
            });
        }
        private EditCell GetEditCell(CellUpdate cell, int index)
        {
            DbCellValue dbCell;

            if (cell == null)
            {
                // Cell hasn't been provided by user yet, attempt to use the default value
                dbCell = new DbCellValue
                {
                    DisplayValue = DefaultValues[index] ?? string.Empty,
                    IsNull       = false, // TODO: This doesn't properly consider null defaults
                    RawObject    = null,
                    RowId        = RowId
                };
            }
            else
            {
                // Cell has been provided by user, so use that
                dbCell = cell.AsDbCellValue;
            }
            return(new EditCell(dbCell, isDirty: true));
        }
Esempio n. 7
0
        /// <summary>
        /// Verifies the column and cell, ensuring a column that needs a value has one.
        /// </summary>
        /// <param name="column">Column that will be inserted into</param>
        /// <param name="cell">Current cell value for this row</param>
        /// <param name="defaultCell">Default value for the column in this row</param>
        /// <exception cref="InvalidOperationException">
        /// Thrown if the column needs a value but it is not provided
        /// </exception>
        /// <returns>
        /// <c>true</c> If the column has a value provided
        /// <c>false</c> If the column does not have a value provided (column is read-only, has default, etc)
        /// </returns>
        private static bool IsCellValueProvided(DbColumnWrapper column, CellUpdate cell, string defaultCell)
        {
            // Skip columns that cannot be updated
            if (!column.IsUpdatable)
            {
                return(false);
            }

            // Make sure a value was provided for the cell
            if (cell == null)
            {
                // If the column is not nullable and there is not default defined, then fail
                if (!column.AllowDBNull.HasTrue() && defaultCell == null)
                {
                    throw new InvalidOperationException(SR.EditDataCreateScriptMissingValue(column.ColumnName));
                }

                // There is a default value (or omitting the value is fine), so trust the db will apply it correctly
                return(false);
            }

            return(true);
        }
        /// <summary>
        /// Generates an INSERT script that will insert this row
        /// </summary>
        /// <param name="forCommand">
        /// If <c>true</c> the script will be generated with an OUTPUT clause for returning all
        /// values in the inserted row (including computed values). The script will also generate
        /// parameters for inserting the values.
        /// If <c>false</c> the script will not have an OUTPUT clause and will have the values
        /// directly inserted into the script (with proper escaping, of course).
        /// </param>
        /// <returns>A script build result object with the script text and any parameters</returns>
        /// <exception cref="InvalidOperationException">
        /// Thrown if there are columns that are not readonly, do not have default values, and were
        /// not assigned values.
        /// </exception>
        private ScriptBuildResult BuildInsertScript(bool forCommand)
        {
            // Process all the columns in this table
            List <string>       inValues      = new List <string>();
            List <string>       inColumns     = new List <string>();
            List <string>       outColumns    = new List <string>();
            List <SqlParameter> sqlParameters = new List <SqlParameter>();

            for (int i = 0; i < AssociatedObjectMetadata.Columns.Length; i++)
            {
                DbColumnWrapper column = AssociatedResultSet.Columns[i];
                CellUpdate      cell   = newCells[i];

                // Add an out column if we're doing this for a command
                if (forCommand)
                {
                    outColumns.Add($"inserted.{SqlScriptFormatter.FormatIdentifier(column.ColumnName)}");
                }

                // Skip columns that cannot be updated
                if (!column.IsUpdatable)
                {
                    continue;
                }

                // Make sure a value was provided for the cell
                if (cell == null)
                {
                    // If the column is not nullable and there is no default defined, then fail
                    if (!column.AllowDBNull.HasTrue() && DefaultValues[i] == null)
                    {
                        throw new InvalidOperationException(SR.EditDataCreateScriptMissingValue(column.ColumnName));
                    }

                    // There is a default value (or omitting the value is fine), so trust the db will apply it correctly
                    continue;
                }

                // Add the input values
                if (forCommand)
                {
                    // Since this script is for command use, add parameter for the input value to the list
                    string paramName = $"@Value{RowId}_{i}";
                    inValues.Add(paramName);

                    SqlParameter param = new SqlParameter(paramName, cell.Column.SqlDbType)
                    {
                        Value = cell.Value
                    };
                    sqlParameters.Add(param);
                }
                else
                {
                    // This script isn't for command use, add the value, formatted for insertion
                    inValues.Add(SqlScriptFormatter.FormatValue(cell.Value, column));
                }

                // Add the column to the in columns
                inColumns.Add(SqlScriptFormatter.FormatIdentifier(column.ColumnName));
            }

            // Begin the script (ie, INSERT INTO blah)
            StringBuilder queryBuilder = new StringBuilder();

            queryBuilder.AppendFormat(InsertScriptStart, AssociatedObjectMetadata.EscapedMultipartName);

            // Add the input columns (if there are any)
            if (inColumns.Count > 0)
            {
                string joinedInColumns = string.Join(", ", inColumns);
                queryBuilder.AppendFormat(InsertScriptColumns, joinedInColumns);
            }

            // Add the output columns (this will be empty if we are not building for command)
            if (outColumns.Count > 0)
            {
                string joinedOutColumns = string.Join(", ", outColumns);
                queryBuilder.AppendFormat(InsertScriptOut, joinedOutColumns);
            }

            // Add the input values (if there any) or use the default values
            if (inValues.Count > 0)
            {
                string joinedInValues = string.Join(", ", inValues);
                queryBuilder.AppendFormat(InsertScriptValues, joinedInValues);
            }
            else
            {
                queryBuilder.AppendFormat(InsertScriptDefault);
            }

            return(new ScriptBuildResult
            {
                ScriptText = queryBuilder.ToString(),
                ScriptParameters = sqlParameters.ToArray()
            });
        }
Esempio n. 9
0
        /// <summary>
        /// Generates a command that can be executed to insert a new row -- and return the newly
        /// inserted row.
        /// </summary>
        /// <param name="connection">The connection the command should be associated with</param>
        /// <returns>Command to insert the new row</returns>
        public override DbCommand GetCommand(DbConnection connection)
        {
            Validate.IsNotNull(nameof(connection), connection);

            // Process the cells and columns
            List <string>       declareColumns       = new List <string>();
            List <string>       inColumnNames        = new List <string>();
            List <string>       outClauseColumnNames = new List <string>();
            List <string>       inValues             = new List <string>();
            List <SqlParameter> inParameters         = new List <SqlParameter>();
            List <string>       selectColumns        = new List <string>();

            for (int i = 0; i < AssociatedObjectMetadata.Columns.Length; i++)
            {
                DbColumnWrapper    column   = AssociatedResultSet.Columns[i];
                EditColumnMetadata metadata = AssociatedObjectMetadata.Columns[i];
                CellUpdate         cell     = newCells[i];

                // Add the output columns regardless of whether the column is read only
                outClauseColumnNames.Add($"inserted.{metadata.EscapedName}");
                declareColumns.Add($"{metadata.EscapedName} {ToSqlScript.FormatColumnType(column, useSemanticEquivalent: true)}");
                selectColumns.Add(metadata.EscapedName);

                // Continue if we're not inserting a value for this column
                if (!IsCellValueProvided(column, cell, DefaultValues[i]))
                {
                    continue;
                }

                // Add the input column
                inColumnNames.Add(metadata.EscapedName);

                // Add the input values as parameters
                string paramName = $"@Value{RowId}_{i}";
                inValues.Add(paramName);
                inParameters.Add(new SqlParameter(paramName, column.SqlDbType)
                {
                    Value = cell.Value
                });
            }

            // Put everything together into a single query
            // Step 1) Build a temp table for inserting output values into
            string tempTableName    = $"@Insert{RowId}Output";
            string declareStatement = string.Format(DeclareStatement, tempTableName, string.Join(", ", declareColumns));

            // Step 2) Build the insert statement
            string joinedOutClauseNames = string.Join(", ", outClauseColumnNames);
            string insertStatement      = inValues.Count > 0
                ? string.Format(InsertOutputValuesStatement,
                                AssociatedObjectMetadata.EscapedMultipartName,
                                string.Join(", ", inColumnNames),
                                joinedOutClauseNames,
                                tempTableName,
                                string.Join(", ", inValues))
                : string.Format(InsertOutputDefaultStatement,
                                AssociatedObjectMetadata.EscapedMultipartName,
                                joinedOutClauseNames,
                                tempTableName);

            // Step 3) Build the select statement
            string selectStatement = string.Format(SelectStatement, string.Join(", ", selectColumns), tempTableName);

            // Step 4) Put it all together into a results object
            StringBuilder query = new StringBuilder();

            query.AppendLine(declareStatement);
            query.AppendLine(insertStatement);
            query.Append(selectStatement);

            // Build the command
            DbCommand command = connection.CreateCommand();

            command.CommandText = query.ToString();
            command.CommandType = CommandType.Text;
            command.Parameters.AddRange(inParameters.ToArray());

            return(command);
        }