GridView и параметры хранимых процедур
От: Pavel Kokorin Россия  
Дата: 21.12.06 14:51
Оценка:
Хучу поделиться мыслями по поводу сабжа. Потратил предыдущие два дня, чтобы решить проблему. Есть БД, все изменения в нее вносятся хранимыми процедурами вида Insert_xxx, Update_xxx, Delete_xxx, но это не суть. Суть в том, чтобы эффективно это использовать с GridView.

Как известно, разрешение конфликтов при аптиместическом обновлении происходит несколькими способами, я выбрал полное сравнение полей при обновлении, и простое удаление по первичному ключу. Т.е. такой немного не последовательный подход.

Так вот, при использовании всего этого совместно с GridView возникает ряд проблем. Начнем с того, что имена параметров хранимых процедур должны совпадать с именами полей соответсвующего GridView. Это справедливо для операции вставки.
При удалении же, в хранимую процедуру передается параметры с именем первичных ключей вид которых можно задать шаблоном OldValuesParametrFormatString, например "имя_столбца"_old. Отлично, если имя парметра хранимой процедуры и имя столбца первичного ключа совпадет, то мы сможем удалить строку.
Есть еще один параметр SqlDataSource, который играет ключевую здесь ключевую роль — это параметр обработки коллизий обновления ConflictDetection. Если этот параметр установлен в OverwriteChanges, то удаление действительно пройдет успешно. Если же он будет равен CompareAllValue, то GridView попытается, помимо первичных ключей, передать в хранимую процедуру удаления предыдущие значения всех полей данных GridView (с именами заданными шаблоном). Естественно, что, если хранимая процедура не содержит такое количество параметров, то при попытке вызова ХП будет сгенерировано исключение, как следствие удаление не пройдет.

Теперь дошел черед до обновления данных. Сначала рассмотрим случай, когда ConflictDetection установлен в OverwriteChanges. В этом случае формируются параметры со значениями первичных ключей (c _old), с новыми данными (без _old) и со старыми данными (с _old), правда значения параметров старых данных установлены у null.
Если же ConflictDetection установлен в CompareAllValue, то параметры старых данных действительно содержат значения, соответсвующие данным изменяемой строки до изменеия.

Получается такая ситуация, что если нужно использовать простое удаление, то ConflictDetection необходимо установить в OverwriteChanges, а если нужно обновление с полным сравнением, то в CompareAllValue. Вместе это работать не будет.

Что же можно с этим поделать. Элегантного решения я пока не нашел. Можно переписать ХП удаления, добавив в них недостающие параметры. Можно поступить другим способом. Зарегистрировав у объекта SqlDataSource обработчик события Deleting, можно удалить все лишние параметры, оставив только значения первичных ключей:
    protected void SqlDataSource1_Deleting(object sender, SqlDataSourceCommandEventArgs e)
    {
        DbParameter delete_param = e.Command.Parameters["@vacancy_id_old"];
        delete_param.ParameterName = "@vacancy_id";
        e.Command.Parameters.Clear();
        e.Command.Parameters.Add(delete_param);
    }

Есть еще одни путь, но он нерабочий У объекта GridView есть событие RowDeleting, в обработчик этого события параметром передается объект класса GridViewDeleteEventArgs, который очень удобно содержит словари первичных ключей и значения старых данных в полят Keys и Values, соответсвенно.
    protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e)
    {
      e.Values.Clear();
    }

К сожалению этот код не работает. При попытке его исполнения генерируется исключение. Тескст которого приведен ниже:
You have specified that your delete command compares all values on SqlDataSource 'SqlDataSource1', but the dictionary passed in for values is empty. Pass in a valid dictionary for delete or change your mode to OverwriteChanges.


Настало время подвести итого. Лично я не понимаю, почему GridView сам изменяет количество параметров, добавляя, по его мнению недостоющие. Такой подход будет работать с обычной sql коммандой, однако при использовании ХП такой подход не приемлем. Было бы правильнее осуществлять привязку параметров к полям GridView. Или хотябы брать за основу множество параметров ХП, не добавляя лишних, а заполняя лишь те из них, имена которых совпадают с именами полей GridView.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.