2013-09-05 3 views
1

Это мой первый запрос в stackoverflow :) У меня есть приложение winforms среднего размера, разработанное на C#, которое подключается к SQL Server 2008, это приложение предназначено для бизнеса (для средних компаний), вы можете делать котировки, счета-фактуры и т. д.Иногда мои новые данные заменяют старые данные в SQL Server

Дело в том, что иногда (не всегда) один пользователь на одном компьютере создает Цитату, эта цитата хранится в SQL и получает идентификатор в качестве результата. Затем, в то же время, другой пользователь на другом компьютере создает другую Цитату и получает тот же идентификатор, и в результате этот последний запрос перекрывает первый.

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

Факты таковы: Это всегда происходит с двумя точными лицами (мы имеем 6 торговых людей, и эта проблема всегда бывает с тем же 2 продавцом) Один из этих продаж человек, работающих на мое приложение удаленно с помощью удаленного рабочего стола так , экземпляр этого приложения запущен на сервере Другой представитель по продажам использует приложение локально на своем компьютере в той же сети, где установлен сервер.

Процесс хранения данных являются следующие:

В структуре базы данных вы найдете 3 таблицы следующим образом: 1) «заголовок данных» котировочной ; 2) «подробно» котировочной 3) Детальная таблица таблицы, связанная для сообщений о проблемах

1) После создания цитаты и нажатия кнопки «Принять» приложение принимает «Заголовок данных» и сохраняет его, в результате оно дает назад идентификатор (а не идентификатор базы данных, но идентификатор возник из какой-либо политики компании) 2) С возвратом идентификатора приложение начинает хранить «d etail "во второй таблице 3) Если пользователь хочет распечатать Quote, создается отчет и для этой цели я временно« копирую »подробные данные из таблицы подробностей в таблицу отчетов

При возникновении ошибки , Я запрашиваю базу данных, и я нашел только одну цитату (последнюю), поэтому я понимаю, что последняя цитата перекрывает первую.

На первый взгляд проблема может быть связана с тем, как я сгенерирую идентификатор, который будет возвращен SQL, так как я создаю на самом деле довольно просто: - Я проверяю последний номер, назначенный для создания идентификатора Quote и регистрации плюс один - Если не существует номера (первые данные в таблице), я просто назначаю его как начальный ID

Почему бы не взять ключ таблицы в качестве идентификатора? поскольку система общается с другой системой, и они нуждаются в specifical идентификаторов из диапазона идентификаторы

код из хранимой процедуры, где создает идентификатор состоит в следующем:

BEGIN TRAN 
DECLARE @newNumDoc INT 
SET @newNumDoc = (ISNULL((SELECT MAX(NUMDOC) FROM REMISION_DBF WHERE idEmpresa = @idEmpresa),0) + 1) 
IF @newNumDoc IS NULL 
    SET @newNumDoc = 1 
COMMIT TRAN 

Итак, кто может мне помочь понять, где проблема, или, по крайней мере, изменить фокус, чтобы избежать дублирования данных?

+0

Если использовать столбец IDENTITY, этого не произойдет. –

ответ

0

Проблема в том, как вы обрабатываете транзакцию и действительно код, который должен быть внутри нее.Ваша транзакция в настоящее время охватывает следующий SQL:

  • Получить наибольшее значение NUMDOC из таблицы базы данных
  • Если это нуль, установите его в 1.

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

Что вам нужно сделать, это больше вдоль линий следующего:

BEGIN TRAN 
DECLARE @newNumDoc INT 
SET @newNumDoc = (ISNULL((SELECT MAX(NUMDOC) FROM REMISION_DBF WHERE idEmpresa = @idEmpresa),0) + 1) 
IF @newNumDoc IS NULL SET @newNumDoc = 1 
INSERT INTO REMISION_DBF (NUMDOC) VALUES (@newNumbDoc) 
COMMIT TRAN 

Это гарантировало бы, что ваш NUMDOC зарезервирован для текущего процесса, а затем, когда дело доходит до написания ваших данных вы просто переключать ваш текущий INSERT для UPDATE.

(Это, очевидно, может поднять другие вопросы с вашей системы, требующие решения отдельно, но это даст вам отправную точку, которая также обеспечивает уникальность NUMDOC значений

Конечно, есть альтернативы,., Например, один возможность заключается в том, чтобы использовать отдельную таблицу из «оговорок», чтобы избежать загрязнения REMISION_DBF. Но даже тогда, тот же BEGIN TRAN ... GET ... INSERT ... COMMIT модель применима.)

Смежные вопросы