SqlDataReader - странный глюк
От: Vladek Россия Github
Дата: 19.06.14 06:10
Оценка:
Вызываю хранимку, в результате 7 столбцов — два последних типа decimal (назовём их A и Б). SqlDataReader считывает их некорректно — значение последнего столбца равно сумме A и Б. Ну то есть, если в БД A=1 и Б=2, то вызов dataReader.GetDecimal(dataReader.GetOrdinal("Б")) даёт 3! Как такое вообще может быть? Иногда такое же происходит и со столбцом A, значения тоже как-то портятся (пока не понял как именно). Остальные столбцы считываются нормально.

ASP.NET MVC 4, .NET 4.5.1, Sql Server 2008 R2 (отдельный сервер)

Вызов через SSMS:
2    2    32    NULL    NULL    85.9789    94.1638
2    2    73    NULL    NULL    98.6300    94.2306
2    2    81    NULL    NULL    99.6151    99.6309
2    2    84    NULL    NULL    7.2424    7.4693


А вот что выдаёт SqlDataReader:
2, 2, 32, , , 85,9789, 180,1427
2, 2, 73, , , 98,6300, 192,8606
2, 2, 81, , , 99,6151, 199,2460
2, 2, 84, , , 7,2424, 14,7117


Ну вот что это, куда копать?

Код вызова предельно прост.
  Скрытый текст
internal static ICollection<T> ExecuteProcedure<T>(
    this IDbConnection connection,
    string procedure, object parameters,
    Func<IDataRecord, T> factory)
{
    using (var command = connection.CreateCommand())
    {
        command.CommandType = CommandType.StoredProcedure;
        command.CommandText = procedure;

        TryAddParameters(command, parameters); // заполняет command.Parameters

        if (connection.State != ConnectionState.Open)
        {
            connection.Open();
        }

        if (log.Switch.ShouldTrace(TraceEventType.Information))
        {
            TraceCommand(command);
        }

        using (var dataReader = command.ExecuteReader(CommandBehavior.SingleResult))
        {
            var items = new List<T>();

            while (dataReader.Read())
            {
                if (log.Switch.ShouldTrace(TraceEventType.Verbose))
                {
                    var values = new object[dataReader.FieldCount];
                    dataReader.GetValues(values);
                    log.TraceData(TraceEventType.Verbose, 1, values); // вот тут уже видно некорректные значения
                }

                items.Add(factory(dataReader)); // factory делает из IDataRecord объект, значения к этому моменту уже испорчены
            }

            return items.ToArray();
        }
    }
}
Re: SqlDataReader - странный глюк
От: Olaf Россия  
Дата: 19.06.14 06:44
Оценка:
Здравствуйте, Vladek, Вы писали:

V>Вызываю хранимку, в результате ...

V>...
V>Ну вот что это, куда копать?

А как выглядит сама процедура ?
Re[2]: SqlDataReader - странный глюк
От: Vladek Россия Github
Дата: 19.06.14 07:25
Оценка: :)
Здравствуйте, Olaf, Вы писали:

O>Здравствуйте, Vladek, Вы писали:


V>>Вызываю хранимку, в результате ...

V>>...
V>>Ну вот что это, куда копать?

O>А как выглядит сама процедура ?


Процедура большая и сложная, но с ней всё в порядке, дело точно не в ней.
Re[3]: SqlDataReader - странный глюк
От: Olaf Россия  
Дата: 19.06.14 07:51
Оценка: +1
Здравствуйте, Vladek, Вы писали:

V>Процедура большая и сложная, но с ней всё в порядке, дело точно не в ней.


Хорошо, что вы уверены в процедуре. Но у меня первые подозрения упали именно на процедуру, т.к. сомневаюсь, что стандартный метод Ado.Net GetValues так предсказуемо просто складывает значения двух выбранных колонок, причем как я понимаю проблема носит плавающий характер, то колонка А, то Б.
Re[4]: SqlDataReader - странный глюк
От: Vladek Россия Github
Дата: 19.06.14 08:06
Оценка:
Здравствуйте, Olaf, Вы писали:

O>Здравствуйте, Vladek, Вы писали:


V>>Процедура большая и сложная, но с ней всё в порядке, дело точно не в ней.


O>Хорошо, что вы уверены в процедуре. Но у меня первые подозрения упали именно на процедуру, т.к. сомневаюсь, что стандартный метод Ado.Net GetValues так предсказуемо просто складывает значения двух выбранных колонок, причем как я понимаю проблема носит плавающий характер, то колонка А, то Б.


Нет, вроде бы имеет значение к какому столбцу обратились раньше. Если прочитать Б, то и А будет некорректным, если сначала прочитать А, то он будет корректным. Б всегда некорректен. Медитирование над исходниками SqlDataReader результатов не принесло. Он читает поля в буфер, но не суммирует их конечно же.
Re: SqlDataReader - странный глюк
От: Философ Ад http://vk.com/id10256428
Дата: 19.06.14 08:20
Оценка:
Здравствуйте, Vladek, Вы писали:

попробуй запустить SqlProfiler и посмотреть, какие данные приходят и какие параметры отправляются.
я никогда ничего подобного не видел, и единственная мысль, которая у меня возникает: отправляются неверные параметры
Всё сказанное выше — личное мнение, если не указано обратное.
Re: SqlDataReader - странный глюк
От: Mihas  
Дата: 19.06.14 08:32
Оценка:
Здравствуйте, Vladek, Вы писали:

А если вместо сложной хранимки дернуть простой select с аналогичной выборкой, ошибка повторится?
Re[4]: SqlDataReader - странный глюк
От: Vladek Россия Github
Дата: 25.06.14 17:50
Оценка:
Здравствуйте, Olaf, Вы писали:

O>Здравствуйте, Vladek, Вы писали:


V>>Процедура большая и сложная, но с ней всё в порядке, дело точно не в ней.


O>Хорошо, что вы уверены в процедуре. Но у меня первые подозрения упали именно на процедуру, т.к. сомневаюсь, что стандартный метод Ado.Net GetValues так предсказуемо просто складывает значения двух выбранных колонок, причем как я понимаю проблема носит плавающий характер, то колонка А, то Б.


Отбой, дело было действительно в процедуре или значениях параметров. Нужно было передавать значение окончания периода времени и вот такой код давал ошибку:
dateTime.Date.AddDays(1d).AddTicks(-1L);

а такой нет:
dateTime.Date.AddDays(1d).AddSeconds(-1d);
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.