На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
  
> Многопользовательская работа с базой, ADO.NET
    День добрый!
    Вопрос - как уважаемые господа поступают, когда требуется многопользовательская работа с базой?
    В частности, как строить поведение проги, дабы юзер имел актуальную информацию и ошибочно не затирал данные, которые успели уже изменить другие юзеры?
      Привет :)
      Для начала, думаю, необходимо определиться с выбором базы. По своему опыту скажу - Access сразу отпадает.
      Ну, а вопрос по поводу "актуальности" данных, весьма деликатен... В любом случае, данные, которые отображаются юзеру на основании запроса "SELECT" - это "снимок", сделанный в момент запроса. Ну, а чтобы никто не мог изменить данные во время редактирования их другим пользователем существует понятие блокировок.

      Транзакции - тоже очень полезная штука. Ну, и на последок, я думаю что нужно как можно больше "нагружать" базу данных, т.е. переносить логику в хранимые процедуры... Вот такие общие соображения
      Сообщение отредактировано: Miha_Dnepr -
        Цитата Miha_Dnepr @
        Транзакции - тоже очень полезная штука. Ну, и на последок, я думаю что нужно как можно больше "нагружать" базу данных, т.е. переносить логику в хранимые процедуры... Вот такие общие соображения

        База, в отличие от сервера приложений, довольно плохо масштабируется, поэтому "нагружать" ее можно только если сервер размером с холодильник, а пользователей планируется мало. В остальных случаях базу грузить зло.

        Что касается вопроса. Существует такая волшебная вещь, как евенты базы. Она может оповещать слушателей об изменениях в таблице. Копать туда. Если работать через DataSet/DataAdapter, то можно определять, что делать с измененными данными, которые были уже изменены другими пользователями.
          Ну, да, с "больше нагружать" я погарячился, имелось ввиду нажождение "золотой середины" в использовании хранимых процедур и нагрузке сервера приложений.
          По-поводу евентов, вопрос интересный... вот, например, меня недавно просвятили, что злополучный Access умудряется выплюнуть событие прежде чем данные реально изменятся. (Я имею ввиду событие DataAdapter.RowUpdated)
            Евенты это очень интересно! Буду балгодарен за пинок в нужном направлении.
            СУБД SQL Server 2005.
              Ап.
              Прболема вернулась, а про евенты базы так ничего и не нашёл :(
                Цитата wdk @
                Прболема вернулась, а про евенты базы так ничего и не нашёл

                см. Notification Service у SQL Server сам не работал, но точно знаю, что евенты он генерит :)

                Ты пишешь про перезатирания данных, это нормально :) и это не самая большая проблема при многопользовательском доступе какая может быть. Ее решить можно транзакциями, в частности выбором нужного уровня изоляции. Посмотри на перечисление IsolationLevel элемент которого передается методу BeginTransaction. Более сложные случае решаются путем обработки соответствующих исключений. Например если ты продал билет, а при попытке сохранить изменения об этом узнаешь, что билет продан кем то другим, то обработав соответствующие исключение ты сможешь уведомить об этом пользователя программы в дружественной форме.
                  Цитата wdk @
                  дабы юзер имел актуальную информацию и ошибочно не затирал данные, которые успели уже изменить другие юзеры?

                  Оптимистические блокировки:
                  В таблице ведется учет, когда запись изменена, или вводится понятие версии записи. При выполнении обновления данных если дата или версия не совпадают с вычитанными - выдавать пользователю сообщение: Данные изменились, перезагрузи. Как это оформить - вопрос архитектуры.
                  2. При выполнении запроса по Update записи, проверять в WHERE не только соответствие первичного ключа, а всех полей, тогда обновление просто не выполнится
                    2 идея интересно! :)
                    Осталось придумать, как заставить SqlCommandBuilder генерить именно такой запрос. Форма универсальная, ручками запрос написать не получится.

                    Добавлено
                    Хм. Прочитал в МСДН:
                    Цитата
                    Optimistic Concurrency Model for Updates and Deletes
                    The logic for generating commands automatically for UPDATE and DELETE statements is based on optimistic concurrency--that is, records are not locked for editing and can be modified by other users or processes at any time. Because a record could have been modified after it was returned from the SELECT statement, but before the UPDATE or DELETE statement is issued, the automatically generated UPDATE or DELETE statement contains a WHERE clause, specifying that a row is only updated if it contains all original values and has not been deleted from the data source. This is done to avoid new data being overwritten. Where an automatically generated update attempts to update a row that has been deleted or that does not contain the original values found in the DataSet, the command does not affect any records and a DBConcurrencyException is thrown.

                    If you want the UPDATE or DELETE to complete regardless of original values, you must explicitly set the UpdateCommand for the DataAdapter and not rely on automatic command generation.


                    Неправда же, затирает он изменения при adapter.Update!

                    Добавлено
                    ExpandedWrap disabled
                                  SqlCommandBuilder cb = new SqlCommandBuilder(adapter);
                                  cb.ConflictOption = ConflictOption.CompareAllSearchableValues;

                    Всё равно в WHERE запроса только ID :/

                    Добавлено
                    Я в тупике.
                    Вот код, заполняющий датасет
                    ExpandedWrap disabled
                                  ds = new DataSet();
                       
                                  SqlConnection conn = new SqlConnection(connString);
                                  adapter = new SqlDataAdapter("SELECT * FROM " + TableName + " ORDER BY ID", conn);
                       
                                  adapter.Fill(ds, TableName);
                       
                                  SqlCommandBuilder cb = new SqlCommandBuilder(adapter);
                                  cb.ConflictOption = ConflictOption.CompareAllSearchableValues;          
                       
                                  adapter.UpdateCommand = cb.GetUpdateCommand();
                                  adapter.DeleteCommand = cb.GetDeleteCommand();
                                  bsMain.DataSource = ds.Tables[TableName]; //binding source
                                  dgvMain.DataSource = bsMain; //datagrid
                       
                                  conn.Close();

                    Где я проганл? :wacko:
                      wdk, я давно не пользовался мастерами и билдерами, но в 1.1 мастер генерил DataAdapter так как я рассказал в 2 :)
                        Попробовал сгенерить мастером, то же самое.
                          Хм.
                          Почему-то билдер не включает поля в WHERE, если они имеют тип varchar или nvarchar. С char(255), допустим, всё нормально. Но мне-то нужны нормальные строки, без кучи пробелов.
                            wdk, попробуй добавить к таблице поле timestamp и использовать CompareRowVersion.
                              Это понятно. Очень желательно по задаче набор полей не менять.. Непонятно, что за странная фигня с полем varchar?
                                Я помню на сайте ASPNETWorld.Ru хорошие статьи на тему ADO.NET были.
                                Про ADO.NET кажется здесь http://www.aspnetworld.ru/Articles/Category/4.html
                                Там как раз обсуждалась многопользовательская работа.
                                Сообщение отредактировано: Meganerd -
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0364 ]   [ 17 queries used ]   [ Generated: 25.04.24, 15:07 GMT ]