示例#1
0
        private void RunTestIteration(SqlConnection con, SqlRandomizer rand, SqlRandomTable table, string tableName)
        {
            // random list of columns
            int columnCount = table.Columns.Count;

            int[] columnIndices = rand.NextIndices(columnCount);
            int   selectedCount = rand.NextIntInclusive(1, maxValueInclusive: columnCount);

            StringBuilder selectBuilder = new StringBuilder();

            table.GenerateSelectFromTableTSql(tableName, selectBuilder, columnIndices, 0, selectedCount);
            SqlCommand cmd = con.CreateCommand();

            cmd.CommandType = CommandType.Text;
            cmd.CommandText = selectBuilder.ToString();

            bool cancel = rand.Next(100) == 0; // in 1% of the cases, call Cancel

            if (cancel)
            {
                int cancelAfterMilliseconds = rand.Next(5);
                int cancelAfterSpinCount    = rand.Next(1000);

                ThreadPool.QueueUserWorkItem((object state) =>
                {
                    for (int i = 0; cancel && i < cancelAfterMilliseconds; i++)
                    {
                        Thread.Sleep(1);
                    }
                    if (cancel && cancelAfterSpinCount > 0)
                    {
                        SpinWait.SpinUntil(() => false, new TimeSpan(cancelAfterSpinCount));
                    }
                    if (cancel)
                    {
                        cmd.Cancel();
                    }
                });
            }

            int             readerRand     = rand.NextIntInclusive(0, maxValueInclusive: 256);
            CommandBehavior readerBehavior = CommandBehavior.Default;

            if (readerRand % 10 == 0)
            {
                readerBehavior = CommandBehavior.SequentialAccess;
            }
            try
            {
                using (SqlDataReader reader = cmd.ExecuteReader(readerBehavior))
                {
                    int row = 0;
                    while (reader.Read())
                    {
                        int rowRand = rand.NextIntInclusive();
                        if (rowRand % 1000 == 0)
                        {
                            // abandon this reader
                            break;
                        }
                        else if (rowRand % 25 == 0)
                        {
                            // skip the row
                            row++;
                            continue;
                        }

                        IList <object> expectedRow = table[row];
                        for (int c = 0; c < reader.FieldCount; c++)
                        {
                            if (rand.NextIntInclusive(0, maxValueInclusive: 10) == 0)
                            {
                                // skip the column
                                continue;
                            }

                            int    expectedTableColumn = columnIndices[c];
                            object expectedValue       = expectedRow[expectedTableColumn];
                            if (table.Columns[expectedTableColumn].CanCompareValues)
                            {
                                Assert.True(expectedValue != null, "FAILED: Null is expected with CanCompareValues");

                                // read the value same way it was written
                                object actualValue = table.Columns[expectedTableColumn].Read(reader, c, expectedValue.GetType());
                                Assert.True(table.Columns[expectedTableColumn].CompareValues(expectedValue, actualValue),
                                            string.Format("FAILED: Data Comparison Failure:\n{0}", table.Columns[expectedTableColumn].BuildErrorMessage(expectedValue, actualValue)));
                            }
                        }

                        row++;
                    }
                }

                // keep last - this will stop the cancel task, if it is still active
                cancel = false;
            }
            catch (SqlException e)
            {
                if (!cancel)
                {
                    throw;
                }

                bool expected = false;

                foreach (SqlError error in e.Errors)
                {
                    if (error.Message == _operationCanceledErrorMessage)
                    {
                        // ignore this one - expected if canceled
                        expected = true;
                        break;
                    }
                    else if (error.Message == _severeErrorMessage)
                    {
                        // A severe error occurred on the current command.  The results, if any, should be discarded.
                        expected = true;
                        break;
                    }
                }

                if (!expected)
                {
                    // rethrow to the user
                    foreach (SqlError error in e.Errors)
                    {
                        Console.WriteLine("{0} {1}", error.Number, error.Message);
                    }
                    throw;
                }
            }
            catch (InvalidOperationException e)
            {
                bool expected = false;

                if (e.Message == _operationCanceledErrorMessage)
                {
                    // "Operation canceled" exception is raised as a SqlException (as one of SqlError objects) and as InvalidOperationException
                    expected = true;
                }

                if (!expected)
                {
                    throw;
                }
            }
        }