SQL Случайные ошибки DBConcurrencyException - VB.Net - PullRequest
0 голосов
/ 05 марта 2020

У меня есть приложение и SQL Сервер, к которому имеют доступ 6 пользователей. Иногда они получают ошибку DBConcurrencyException. Иногда я имею в виду, что я получаю копию их ошибки максимум несколько раз в неделю - и обычно не одним и тем же пользователем. Я решил, что это не потому, что другой пользователь также обновил ту же «запись». У меня есть ощущение, что это как-то связано с преобразованием десятичных дробей? между сервером и рабочей станцией пользователей. Однако я не могу повторить ошибку.

Я попытался обновить запись в приложении одновременно с сервером. Что бы ни заканчивалось первым, побеждает. Но нет ошибки. Поскольку я не могу воспроизвести эту ошибку и не знаю, как ее «заставить», я не могу найти аргументацию или решение.

Итак, 2 вопроса:

  1. Является ли мое мнение вероятным, что ошибка связана с преобразованием данных? Если да, как я могу проверить и / или исправить эту проблему?

  2. Есть ли способ, которым я могу форсировать или подделать исключение, чтобы найти правильное решение? Я хотел бы знать точно, ПОЧЕМУ ошибка происходит, прежде чем я начну пытаться заставить обновления на сервер.

Не уверен, какой код будет полезен здесь, но я использую SqlDataAdapter.Update для обновления сервера с изменениями.

Запрос на обновление сборки:

SQLcmd = New SqlCommand("
    UPDATE [ACL].data_Demog_BGL SET
       [Offline]  = @Offline
       ,[ID_BGL_Assay]  = @Assay
       ,[Barcode_Number]  = @BarNum
       ,[Result]  = @Result
       ,[Result_Type]  = @RType
       ,[ID_Test_Outcome]  = @TOutcome
       ,[CLIR_Request]  = @CReq
       ,[CLIR_Entry]  = @CEntry
       ,[Tasklist]  = @Tasklist
       ,[Sequence]  = @Seq
       ,[CLIR_Date]  = @CDate
    WHERE ID_Demog_BGL = @ID
    ", Vars.sqlConnACL)

With SQLcmd.Parameters
        .Add("@Offline", SqlDbType.Bit, 0, "Offline")
        .Add("@Assay", SqlDbType.Int, 0, "ID_BGL_Assay")
        .Add("@BarNum", SqlDbType.NVarChar, 255, "Barcode_Number")
        .Add("@Result", SqlDbType.NVarChar, 255, "Result")
        .Add("@RType", SqlDbType.NVarChar, 255, "Result_Type")
        .Add("@TOutcome", SqlDbType.Int, 0, "ID_Test_Outcome")
        .Add("@CReq", SqlDbType.Bit, 0, "CLIR_Request")
        .Add("@CEntry", SqlDbType.NVarChar, 255, "CLIR_Entry")
        .Add("@Tasklist", SqlDbType.NVarChar, 255, "Tasklist")
        .Add("@Seq", SqlDbType.NVarChar, 255, "Sequence")
        .Add("@CDate", SqlDbType.Date, 0, "CLIR_Date")
        .Add("@ID", SqlDbType.Int, 0, "ID_Demog_BGL")
End With

da_BGLAssay.UpdateCommand = SQLcmd

и ...

Me.Validate()
bsBGL.EndEdit()
da_BGLAssay.Update(dt_BGLAssay)
da_BGLAssay.Fill(dt_BGLAssay)

1 Ответ

0 голосов
/ 06 марта 2020

SQL Сервер имеет несколько опций для отслеживания изменений в таблицах и некоторые методы для определения, кто удалил данные - проблема в том, что большинство приложений в настоящее время используют свою собственную пользовательскую систему, и каждый / веб-сервер использует общий логин, чтобы не очень помогает ...

Если вам повезло иметь несколько пользователей БД, возможно, вы уже настроены: https://www.mssqltips.com/sqlservertip/3090/how-to-find-user-who-ran-drop-or-delete-statements-on-your-sql-server-objects/ или https://dba.stackexchange.com/questions/4269/how-to-find-out-who-deleted-some-data-sql-server

Если вы развернули свою собственную пользовательскую систему, то вам, возможно, придется развернуть что-то, чтобы заняться журналированием. Конечно, это могут быть программные c и минимальные усилия, но какие усилия будут зависеть от того, как реализован ваш уровень данных

Вы также можете установить триггер для регистрации времени и того, какие данные удаляются - если эти записи исчезает при закрытии офиса, возможно, какое-то автоматическое задание. Если у вас есть таблица времени входа и выхода из системы (относительно тривиально), это может помочь определить человека


Обработка DBConcurrencyExcpetion также возможна: когда вы ловите это, в вашем случае вы знаете, что запись была удалена. Просто предложите восстановить его, и если пользователь скажет «да», измените RowState с «Изменено» на «Добавлен» и сохраните его снова, чтобы использовать INSERT вместо запроса UPDATE

Обратите внимание, что если вы просто делаете Update(datatable) тогда адаптер может быть ОБНОВЛЕНИЕ / ВСТАВИТЬ / УДАЛИТЬ сотни строк, и вы можете не знать, какой из них вызвал исключение. Вы можете go строка за строкой в ​​al oop


О, это только заставило меня задуматься о чем-то другом; известно ли вам, что хотя метод dataapter / tableadapter для сохранения изменений в таблице данных называется Update(), он будет вызывать INSERT / UPDATE / DELETE в зависимости от того, добавлен ли / изменен / удален RowState? Я спрашиваю, потому что некоторые люди думают, что Update() только обновляется, но если в вашей таблице данных есть несколько удаленных строк, при вызове Update эти строки будут удалены из БД

Update() было бы лучше выкл. вызвано SaveChanges .. но да, просто если вы не знали - это может быть причиной вашего удаления, если случайные записи в вашем DT помечены как удаленные, и вы Update() намереваетесь сохранить изменения в измененной строке

...