C # метод для блокировки таблицы SQL Server
У меня есть программа на C #, которая должна выполнить группу массовых обновлений (20k +) для таблицы SQL Server. Поскольку другие пользователи могут обновлять эти записи по одной через веб-сайт интрасети, нам необходимо создать программу на C # с возможностью блокировки таблицы. После того, как таблица заблокирована, чтобы другой пользователь не мог вносить изменения / поиски, нам необходимо предварительно выполнить запрошенные обновления / вставки.
Поскольку мы обрабатываем так много записей, мы не можем использоватьTransactionScope
(сначала это казалось самым простым способом) из-за того, что наша транзакция обрабатываетсяMSDTC сервис, Нам нужно использовать другой метод.
Основываясь на том, что я прочитал в Интернете, используяSqlTransaction
объект, казалось, был лучшим методом, однако я не могу заставить таблицу заблокироваться. Когда программа запускается, и я выполняю код, указанный ниже, я все еще могу выполнять обновления и выполнять поиск по сайту в интрасети.
Мой вопрос двоякий. Я используюSqlTransaction
должным образом? Если да (или даже если нет), есть ли лучший способ получения блокировки таблицы, который позволяет текущей запущенной программе выполнять поиск и обновлять преформу?
Я хотел бы, чтобы таблица была заблокирована, пока программа выполняет приведенный ниже код.
C #
SqlConnection dbConnection = new SqlConnection(dbConn);
dbConnection.Open();
using (SqlTransaction transaction = dbConnection.BeginTransaction(IsolationLevel.Serializable))
{
//Instantiate validation object with zip and channel values
_allRecords = GetRecords();
validation = new Validation();
validation.SetLists(_allRecords);
while (_reader.Read())
{
try
{
record = new ZipCodeTerritory();
_errorMsg = string.Empty;
//Convert row to ZipCodeTerritory type
record.ChannelCode = _reader[0].ToString();
record.DrmTerrDesc = _reader[1].ToString();
record.IndDistrnId = _reader[2].ToString();
record.StateCode = _reader[3].ToString().Trim();
record.ZipCode = _reader[4].ToString().Trim();
record.LastUpdateId = _reader[7].ToString();
record.ErrorCodes = _reader[8].ToString();
record.Status = _reader[9].ToString();
record.LastUpdateDate = DateTime.Now;
//Handle DateTime types separetly
DateTime value = new DateTime();
if (DateTime.TryParse(_reader[5].ToString(), out value))
{
record.EndDate = Convert.ToDateTime(_reader[5].ToString());
}
else
{
_errorMsg += "Invalid End Date; ";
}
if (DateTime.TryParse(_reader[6].ToString(), out value))
{
record.EffectiveDate = Convert.ToDateTime(_reader[6].ToString());
}
else
{
_errorMsg += "Invalid Effective Date; ";
}
//Do not process if we're missing LastUpdateId
if (string.IsNullOrEmpty(record.LastUpdateId))
{
_errorMsg += "Missing last update Id; ";
}
//Make sure primary key is valid
if (_reader[10] != DBNull.Value)
{
int id = 0;
if (int.TryParse(_reader[10].ToString(), out id))
{
record.Id = id;
}
else
{
_errorMsg += "Invalid Id; ";
}
}
//Validate business rules if data is properly formatted
if (string.IsNullOrWhiteSpace(_errorMsg))
{
_errorMsg = validation.ValidateZipCode(record);
}
//Skip record if any errors found
if (!string.IsNullOrWhiteSpace(_errorMsg))
{
_issues++;
//Convert to ZipCodeError type in case we have data/formatting errors
_errors.Add(new ZipCodeError(_reader), _errorMsg);
continue;
}
else if (flag)
{
//Separate updates to appropriate list
SendToUpdates(record);
}
}
catch (Exception ex)
{
_errors.Add(new ZipCodeError(_reader), "Job crashed reading this record, please review all columns.");
_issues++;
}
}//End while
//Updates occur in one of three methods below. If I step through the code,
//and stop the program here, before I enter any of the methods, and then
//make updates to the same records via our intranet site the changes
//made on the site go through. No table locking has occured at this point.
if (flag)
{
if (_insertList.Count > 0)
{
Updates.Insert(_insertList, _errors);
}
if (_updateList.Count > 0)
{
_updates = Updates.Update(_updateList, _errors);
_issues += _updateList.Count - _updates;
}
if (_autotermList.Count > 0)
{
//_autotermed = Updates.Update(_autotermList, _errors);
_autotermed = Updates.UpdateWithReporting(_autotermList, _errors);
_issues += _autotermList.Count - _autotermed;
}
}
transaction.Commit();
}