public async Task GetEditRowNoAdditions()
        {
            // Setup: Generate a standard row create
            RowCreate rc = await GetStandardRowCreate();

            // If: I request an edit row from the row create
            EditRow er = rc.GetEditRow(null);

            // Then:
            // ... The row should not be null
            Assert.NotNull(er);

            // ... The row should not be clean
            Assert.True(er.IsDirty);
            Assert.Equal(EditRow.EditRowState.DirtyInsert, er.State);

            // ... The row should have a bunch of empty cells (equal to number of columns) and all are dirty
            Assert.Equal(rc.newCells.Length, er.Cells.Length);
            Assert.All(er.Cells, ec =>
            {
                Assert.Equal(string.Empty, ec.DisplayValue);
                Assert.False(ec.IsNull);
                Assert.True(ec.IsDirty);
            });
        }
        public async Task SetCellNoChange()
        {
            // Setup: Generate a row create
            RowCreate rc = await GetStandardRowCreate();

            // If: I set a cell in the newly created row to something that doesn't need changing
            const string         updateValue = "1";
            EditUpdateCellResult eucr        = rc.SetCell(0, updateValue);

            // Then:
            // ... The returned value should be equal to what we provided
            Assert.NotNull(eucr);
            Assert.NotNull(eucr.Cell);
            Assert.Equal(updateValue, eucr.Cell.DisplayValue);
            Assert.False(eucr.Cell.IsNull);

            // ... The returned value should be dirty
            Assert.NotNull(eucr.Cell.IsDirty);

            // ... The row should still be dirty
            Assert.True(eucr.IsRowDirty);

            // ... There should be a cell update in the cell list
            Assert.NotNull(rc.newCells[0]);
        }
        public async Task GetCommand(bool includeIdentity, int defaultCols, int nullableCols, int valuesToSkip, RegexExpectedOutput expectedOutput)
        {
            // Setup:
            // ... Generate the parameters for the row create
            Common.TestDbColumnsWithTableMetadata data = new Common.TestDbColumnsWithTableMetadata(false, includeIdentity, defaultCols, nullableCols);
            ResultSet rs = await Common.GetResultSet(data.DbColumns, includeIdentity);

            // ... Mock db connection for building the command
            var mockConn = new TestSqlConnection(null);

            // ... Create a row create and set the appropriate number of cells
            RowCreate rc = new RowCreate(100, rs, data.TableMetadata);

            Common.AddCells(rc, valuesToSkip);

            // If: I ask for the command for the row insert
            DbCommand cmd = rc.GetCommand(mockConn);

            // Then:
            // ... The command should not be null
            Assert.NotNull(cmd);

            // ... There should be parameters in it
            Assert.Equal(expectedOutput.ExpectedInValues, cmd.Parameters.Count);

            // ... The script should match the expected regex output
            ValidateCommandAgainstRegex(cmd.CommandText, expectedOutput);
        }
        public async Task GetEditRowWithAdditions()
        {
            // Setp: Generate a row create with a cell added to it
            RowCreate rc = await GetStandardRowCreate();

            const string setValue = "foo";

            rc.SetCell(0, setValue);

            // If: I request an edit row from the row create
            EditRow er = rc.GetEditRow(null);

            // Then:
            // ... The row should not be null and contain the same number of cells as columns
            Assert.NotNull(er);
            Assert.Equal(EditRow.EditRowState.DirtyInsert, er.State);

            // ... The row should not be clean
            Assert.True(er.IsDirty);
            Assert.Equal(EditRow.EditRowState.DirtyInsert, er.State);

            // ... The row should have a single non-empty cell at the beginning that is dirty
            Assert.Equal(setValue, er.Cells[0].DisplayValue);
            Assert.False(er.Cells[0].IsNull);
            Assert.True(er.Cells[0].IsDirty);

            // ... The rest of the cells should be blank, but dirty
            for (int i = 1; i < er.Cells.Length; i++)
            {
                EditCell ec = er.Cells[i];
                Assert.Equal(string.Empty, ec.DisplayValue);
                Assert.False(ec.IsNull);
                Assert.True(ec.IsDirty);
            }
        }
Exemple #5
0
        /// <summary>
        /// Creates a new row update and adds it to the update cache
        /// </summary>
        /// <exception cref="InvalidOperationException">If inserting into cache fails</exception>
        /// <returns>The internal ID of the newly created row</returns>
        public EditCreateRowResult CreateRow()
        {
            ThrowIfNotInitialized();

            // Create a new row ID (atomically, since this could be accesses concurrently)
            long newRowId = NextRowId++;

            // Create a new row create update and add to the update cache
            RowCreate newRow = new RowCreate(newRowId, associatedResultSet, objectMetadata);

            if (!EditCache.TryAdd(newRowId, newRow))
            {
                // Revert the next row ID
                NextRowId--;
                throw new InvalidOperationException(SR.EditDataFailedAddRow);
            }

            EditCreateRowResult output = new EditCreateRowResult
            {
                NewRowId      = newRow.RowId,
                DefaultValues = newRow.DefaultValues
            };

            return(output);
        }
        public async Task GetScript(bool includeIdentity)
        {
            // Setup: Generate the parameters for the row create
            const long rowId = 100;

            DbColumn[] columns = Common.GetColumns(includeIdentity);
            ResultSet  rs      = await Common.GetResultSet(columns, includeIdentity);

            EditTableMetadata etm = Common.GetStandardMetadata(columns);

            // If: I ask for a script to be generated without an identity column
            RowCreate rc = new RowCreate(rowId, rs, etm);

            Common.AddCells(rc, includeIdentity);
            string script = rc.GetScript();

            // Then:
            // ... The script should not be null,
            Assert.NotNull(script);

            // ... It should be formatted as an insert script
            Regex r = new Regex(@"INSERT INTO (.+)\((.*)\) VALUES \((.*)\)");
            var   m = r.Match(script);

            Assert.True(m.Success);

            // ... It should have 3 columns and 3 values (regardless of the presence of an identity col)
            string tbl  = m.Groups[1].Value;
            string cols = m.Groups[2].Value;
            string vals = m.Groups[3].Value;

            Assert.Equal(etm.EscapedMultipartName, tbl);
            Assert.Equal(3, cols.Split(',').Length);
            Assert.Equal(3, vals.Split(',').Length);
        }
        public async Task SetCellNull()
        {
            // Setup: Generate a row create
            var data = new Common.TestDbColumnsWithTableMetadata(false, false, 0, 3);
            var rs   = await Common.GetResultSet(data.DbColumns, false);

            var rc = new RowCreate(100, rs, data.TableMetadata);

            // If: I set a cell in the newly created row to null
            const string         nullValue = "NULL";
            EditUpdateCellResult eucr      = rc.SetCell(0, nullValue);

            // Then:
            // ... The returned value should be equal to what we provided
            Assert.NotNull(eucr);
            Assert.NotNull(eucr.Cell);
            Assert.Equal(nullValue, eucr.Cell.DisplayValue);
            Assert.True(eucr.Cell.IsNull);

            // ... The returned value should be dirty
            Assert.NotNull(eucr.Cell.IsDirty);

            // ... The row should still be dirty
            Assert.True(eucr.IsRowDirty);

            // ... There should be a cell update in the cell list
            Assert.NotNull(rc.newCells[0]);
        }
        public async Task GetEditRowWithDefaultValue()
        {
            // Setup: Generate a row create with default values
            const long rowId = 100;

            Common.TestDbColumnsWithTableMetadata data = new Common.TestDbColumnsWithTableMetadata(false, false, 3, 0);
            ResultSet rs = await Common.GetResultSet(data.DbColumns, false);

            RowCreate rc = new RowCreate(rowId, rs, data.TableMetadata);

            // If: I request an edit row from the row create
            EditRow er = rc.GetEditRow(null);

            // Then:
            // ... The row should not be null
            Assert.NotNull(er);

            // ... The row should not be clean
            Assert.True(er.IsDirty);
            Assert.Equal(EditRow.EditRowState.DirtyInsert, er.State);

            // ... The row sould have a bunch of default values (equal to number of columns) and all are dirty
            Assert.Equal(rc.newCells.Length, er.Cells.Length);
            Assert.All(er.Cells, ec =>
            {
                Assert.Equal(Common.DefaultValue, ec.DisplayValue);
                Assert.False(ec.IsNull);    // TODO: Update when we support null default values better
                Assert.True(ec.IsDirty);
            });
        }
        public async Task RevertCellThatWasSet(int defaultCols)
        {
            // Setup:
            // ... Generate the parameters for the row create
            Common.TestDbColumnsWithTableMetadata data = new Common.TestDbColumnsWithTableMetadata(false, false, defaultCols, 0);
            ResultSet rs = await Common.GetResultSet(data.DbColumns, false);

            RowCreate rc = new RowCreate(100, rs, data.TableMetadata);

            rc.SetCell(0, "1");

            // If: I attempt to revert a cell that was set
            EditRevertCellResult result = rc.RevertCell(0);

            // Then:
            // ... We should get a result back
            Assert.NotNull(result);

            // ... We should get back an edit cell with a value based on the default value
            string expectedDisplayValue = defaultCols > 0 ? Common.DefaultValue : string.Empty;

            Assert.NotNull(result.Cell);
            Assert.Equal(expectedDisplayValue, result.Cell.DisplayValue);
            Assert.False(result.Cell.IsNull);    // TODO: Modify to support null defaults

            // ... The row should be dirty
            Assert.True(result.IsRowDirty);

            // ... The cell should no longer be set
            Assert.Null(rc.newCells[0]);
        }
        [InlineData(100)]       // Way too large value
        public async Task SetCellOutOfRange(int columnId)
        {
            // Setup: Generate a row create
            RowCreate rc = await GetStandardRowCreate();

            // If: I attempt to set a cell on a column that is out of range, I should get an exception
            Assert.Throws <ArgumentOutOfRangeException>(() => rc.SetCell(columnId, string.Empty));
        }
        public async Task GetCommandNullConnection()
        {
            // Setup: Create a row create
            RowCreate rc = await GetStandardRowCreate();

            // If: I attempt to create a command with a null connection
            // Then: It should throw an exception
            Assert.Throws <ArgumentNullException>(() => rc.GetCommand(null));
        }
        public async Task GetScriptMissingCell()
        {
            // Setup: Generate the parameters for the row create
            RowCreate rc = await GetStandardRowCreate();

            // If: I ask for a script to be generated without setting any values
            // Then: An exception should be thrown for missing cells
            Assert.Throws <InvalidOperationException>(() => rc.GetScript());
        }
        [InlineData(100)]       // Way too large value
        public async Task RevertCellOutOfRange(int columnId)
        {
            // Setup: Generate the row create
            RowCreate rc = await GetStandardRowCreate();

            // If: I attempt to revert a cell that is out of range
            // Then: I should get an exception
            Assert.Throws <ArgumentOutOfRangeException>(() => rc.RevertCell(columnId));
        }
        public async Task GetScriptMissingCell(bool includeIdentity, int defaultCols, int nullableCols, int valuesToSkipSetting)
        {
            // Setup: Generate the parameters for the row create
            var data = new Common.TestDbColumnsWithTableMetadata(false, includeIdentity, defaultCols, nullableCols);
            var rs   = await Common.GetResultSet(data.DbColumns, includeIdentity);

            RowCreate rc = new RowCreate(100, rs, data.TableMetadata);

            // If: I ask for a script to be generated without setting any values
            // Then: An exception should be thrown for missing cells
            Assert.Throws <InvalidOperationException>(() => rc.GetScript());
        }
        public async Task GetCommand(bool includeIdentity)
        {
            // Setup:
            // ... Create a row create with cell updates
            const long rowId   = 100;
            var        columns = Common.GetColumns(includeIdentity);
            var        rs      = await Common.GetResultSet(columns, includeIdentity);

            var       etm = Common.GetStandardMetadata(columns);
            RowCreate rc  = new RowCreate(rowId, rs, etm);

            Common.AddCells(rc, includeIdentity);

            // ... Mock db connection for building the command
            var mockConn = new TestSqlConnection(null);

            // If: I attempt to get a command for the edit
            DbCommand cmd = rc.GetCommand(mockConn);

            // Then:
            // ... The command should not be null
            Assert.NotNull(cmd);

            // ... There should be parameters in it
            Assert.Equal(3, cmd.Parameters.Count);

            // ... It should be formatted into an insert script with output
            Regex r = new Regex(@"INSERT INTO (.+)\((.+)\) OUTPUT (.+) VALUES \((.+)\)");
            var   m = r.Match(cmd.CommandText);

            Assert.True(m.Success);

            // ... There should be a table
            string tbl = m.Groups[1].Value;

            Assert.Equal(etm.EscapedMultipartName, tbl);

            // ... There should be 3 columns for input
            string inCols = m.Groups[2].Value;

            Assert.Equal(3, inCols.Split(',').Length);

            // ... There should be 3 OR 4 columns for output that are inserted.
            string[] outCols = m.Groups[3].Value.Split(',');
            Assert.Equal(includeIdentity ? 4 : 3, outCols.Length);
            Assert.All(outCols, s => Assert.StartsWith("inserted.", s.Trim()));

            // ... There should be 3 parameters
            string[] param = m.Groups[4].Value.Split(',');
            Assert.Equal(3, param.Length);
            Assert.All(param, s => Assert.StartsWith("@Value", s.Trim()));
        }
        public async Task RowCreateConstruction()
        {
            // Setup: Create the values to store
            const long rowId = 100;

            Common.TestDbColumnsWithTableMetadata data = new Common.TestDbColumnsWithTableMetadata(false, false, 0, 0);
            ResultSet rs = await Common.GetResultSet(data.DbColumns, false);

            // If: I create a RowCreate instance
            RowCreate rc = new RowCreate(rowId, rs, data.TableMetadata);

            // Then: The values I provided should be available
            Assert.Equal(rowId, rc.RowId);
            Assert.Equal(rs, rc.AssociatedResultSet);
            Assert.Equal(data.TableMetadata, rc.AssociatedObjectMetadata);
        }
        public async Task GetCommandMissingCellNoDefault(bool includeIdentity, int defaultCols, int nullableCols,
                                                         int valuesToSkip)
        {
            // Setup:
            // ... Generate the row create object
            Common.TestDbColumnsWithTableMetadata data = new Common.TestDbColumnsWithTableMetadata(false, includeIdentity, defaultCols, nullableCols);
            ResultSet rs = await Common.GetResultSet(data.DbColumns, includeIdentity);

            RowCreate rc = new RowCreate(100, rs, data.TableMetadata);

            // ... Create a mock db connection for building the command
            var mockConn = new TestSqlConnection();

            // If: I ask for a script to be generated without setting all the required values
            // Then: An exception should be thrown for the missing cells
            Assert.Throws <InvalidOperationException>(() => rc.GetCommand(mockConn));
        }
Exemple #18
0
        /// <summary>
        /// Creates a new row update and adds it to the update cache
        /// </summary>
        /// <exception cref="InvalidOperationException">If inserting into cache fails</exception>
        /// <returns>The internal ID of the newly created row</returns>
        public EditCreateRowResult CreateRow()
        {
            ThrowIfNotInitialized();

            // Create a new row ID (atomically, since this could be accesses concurrently)
            long newRowId = NextRowId++;

            // Create a new row create update and add to the update cache
            RowCreate newRow = new RowCreate(newRowId, associatedResultSet, objectMetadata);

            if (!EditCache.TryAdd(newRowId, newRow))
            {
                // Revert the next row ID
                NextRowId--;
                throw new InvalidOperationException(SR.EditDataFailedAddRow);
            }

            // Set the default values of the row if we know them
            string[] defaultValues = new string[objectMetadata.Columns.Length];
            for (int i = 0; i < objectMetadata.Columns.Length; i++)
            {
                EditColumnMetadata col = objectMetadata.Columns[i];

                // If the column is calculated, return the calculated placeholder as the display value
                if (col.IsCalculated.HasTrue())
                {
                    defaultValues[i] = SR.EditDataComputedColumnPlaceholder;
                }
                else
                {
                    if (col.DefaultValue != null)
                    {
                        newRow.SetCell(i, col.DefaultValue);
                    }
                    defaultValues[i] = col.DefaultValue;
                }
            }

            EditCreateRowResult output = new EditCreateRowResult
            {
                NewRowId      = newRowId,
                DefaultValues = defaultValues
            };

            return(output);
        }
        public async Task RowCreateConstruction()
        {
            // Setup: Create the values to store
            const long rowId = 100;

            DbColumn[] columns = Common.GetColumns(false);
            ResultSet  rs      = await Common.GetResultSet(columns, false);

            EditTableMetadata etm = Common.GetStandardMetadata(columns);

            // If: I create a RowCreate instance
            RowCreate rc = new RowCreate(rowId, rs, etm);

            // Then: The values I provided should be available
            Assert.Equal(rowId, rc.RowId);
            Assert.Equal(rs, rc.AssociatedResultSet);
            Assert.Equal(etm, rc.AssociatedObjectMetadata);
        }
        public async Task ApplyChanges(bool includeIdentity)
        {
            // Setup:
            // ... Generate the parameters for the row create
            const long rowId = 100;

            Common.TestDbColumnsWithTableMetadata data = new Common.TestDbColumnsWithTableMetadata(false, includeIdentity, 0, 0);
            ResultSet rs = await Common.GetResultSet(data.DbColumns, includeIdentity);

            // ... Setup a db reader for the result of an insert
            var newRowReader = Common.GetNewRowDataReader(data.DbColumns, includeIdentity);

            // If: I ask for the change to be applied
            RowCreate rc = new RowCreate(rowId, rs, data.TableMetadata);
            await rc.ApplyChanges(newRowReader);

            // Then: The result set should have an additional row in it
            Assert.Equal(2, rs.RowCount);
        }
        public async Task ApplyChanges(bool includeIdentity)
        {
            // Setup:
            // ... Generate the parameters for the row create
            const long rowId = 100;

            DbColumn[] columns = Common.GetColumns(includeIdentity);
            ResultSet  rs      = await Common.GetResultSet(columns, includeIdentity);

            EditTableMetadata etm = Common.GetStandardMetadata(columns);

            // ... Setup a db reader for the result of an insert
            var newRowReader = Common.GetNewRowDataReader(columns, includeIdentity);

            // If: I ask for the change to be applied
            RowCreate rc = new RowCreate(rowId, rs, etm);
            await rc.ApplyChanges(newRowReader);

            // Then: The result set should have an additional row in it
            Assert.Equal(2, rs.RowCount);
        }
        public async Task SetCellHasCorrections()
        {
            // Setup:
            // ... Generate a result set with a single binary column
            DbColumn[] cols = { new TestDbColumn
                                {
                                    DataType     = typeof(byte[]),
                                    DataTypeName = "binary"
                                } };
            object[][] rows          = {};
            var        testResultSet = new TestResultSet(cols, rows);
            var        testReader    = new TestDbDataReader(new[] { testResultSet }, false);
            var        rs            = new ResultSet(0, 0, MemoryFileSystem.GetFileStreamFactory());
            await rs.ReadResultToEnd(testReader, CancellationToken.None);

            // ... Generate the metadata
            var etm = Common.GetCustomEditTableMetadata(cols);

            // ... Create the row create
            RowCreate rc = new RowCreate(100, rs, etm);

            // If: I set a cell in the newly created row to something that will be corrected
            EditUpdateCellResult eucr = rc.SetCell(0, "1000");

            // Then:
            // ... The returned value should be equal to what we provided
            Assert.NotNull(eucr);
            Assert.NotNull(eucr.Cell);
            Assert.NotEqual("1000", eucr.Cell.DisplayValue);
            Assert.False(eucr.Cell.IsNull);

            // ... The returned value should be dirty
            Assert.NotNull(eucr.Cell.IsDirty);

            // ... The row should still be dirty
            Assert.True(eucr.IsRowDirty);

            // ... There should be a cell update in the cell list
            Assert.NotNull(rc.newCells[0]);
        }
        public async Task RevertCellNotSet()
        {
            // Setup: Generate the row create
            RowCreate rc = await GetStandardRowCreate();

            // If: I attempt to revert a cell that has not been set
            EditRevertCellResult result = rc.RevertCell(0);

            // Then:
            // ... We should get a result back
            Assert.NotNull(result);

            // ... We should get a null cell back
            // @TODO: Check for a default value when we support it
            Assert.Null(result.Cell);

            // ... The row should be dirty
            Assert.True(result.IsRowDirty);

            // ... The cell should no longer be set
            Assert.Null(rc.newCells[0]);
        }
        public async Task GetScript(bool includeIdentity, int colsWithDefaultConstraints, int colsThatAllowNull, int valuesToSkipSetting, RegexExpectedOutput expectedOutput)
        {
            // Setup:
            // ... Generate the parameters for the row create
            Common.TestDbColumnsWithTableMetadata data = new Common.TestDbColumnsWithTableMetadata(false, includeIdentity, colsWithDefaultConstraints, colsThatAllowNull);
            ResultSet rs = await Common.GetResultSet(data.DbColumns, includeIdentity);

            // ... Create a row create and set the appropriate number of cells
            RowCreate rc = new RowCreate(100, rs, data.TableMetadata);

            Common.AddCells(rc, valuesToSkipSetting);

            // If: I ask for the script for the row insert
            string script = rc.GetScript();

            // Then:
            // ... The script should not be null
            Assert.NotNull(script);

            // ... The script should match the expected regex output
            ValidateScriptAgainstRegex(script, expectedOutput);
        }
        public async Task SetCellNull()
        {
            // Setup: Generate a row create
            RowCreate rc = await GetStandardRowCreate();

            // If: I set a cell in the newly created row to null
            EditUpdateCellResult eucr = rc.SetCell(0, "NULL");

            // Then:
            // ... The returned value should be equal to what we provided
            Assert.NotNull(eucr);
            Assert.NotNull(eucr.Cell);
            Assert.NotEmpty(eucr.Cell.DisplayValue);
            Assert.True(eucr.Cell.IsNull);

            // ... The returned value should be dirty
            Assert.NotNull(eucr.Cell.IsDirty);

            // ... The row should still be dirty
            Assert.True(eucr.IsRowDirty);

            // ... There should be a cell update in the cell list
            Assert.NotNull(rc.newCells[0]);
        }
        public async Task GetEditRowWithCalculatedValue()
        {
            // Setup: Generate a row create with an identity column
            const long rowId = 100;

            Common.TestDbColumnsWithTableMetadata data = new Common.TestDbColumnsWithTableMetadata(false, true, 0, 0);
            ResultSet rs = await Common.GetResultSet(data.DbColumns, true);

            RowCreate rc = new RowCreate(rowId, rs, data.TableMetadata);

            // If: I request an edit row from the row created
            EditRow er = rc.GetEditRow(null);

            // Then:
            // ... The row should not be null
            Assert.NotNull(er);
            Assert.Equal(er.Id, rowId);

            // ... The row should not be clean
            Assert.True(er.IsDirty);
            Assert.Equal(EditRow.EditRowState.DirtyInsert, er.State);

            // ... The row should have a TBD for the identity column
            Assert.Equal(rc.newCells.Length, er.Cells.Length);
            Assert.Equal(SR.EditDataComputedColumnPlaceholder, er.Cells[0].DisplayValue);
            Assert.False(er.Cells[0].IsNull);
            Assert.True(er.Cells[0].IsDirty);

            // ... The rest of the cells should have empty display values
            Assert.All(er.Cells.Skip(1), ec =>
            {
                Assert.Equal(string.Empty, ec.DisplayValue);
                Assert.False(ec.IsNull);
                Assert.True(ec.IsDirty);
            });
        }