Мы пишем подпрограмму, которая либо возвращает редактируемый объект, либо объект состояния, который говорит, что базовая запись заблокирована.
Мы используем C# и .NET Framework 4.8 с драйвером ODBC Progress OpenEdge для базы данных OpenEdge. Запись может быть заблокирована устаревшим кодом ABL, поэтому мы хотим проверить транзакцию ReadCommitted, чтобы убедиться, что для нас безопасно начинать ее редактирование.
Функционально код работает нормально, делая именно то, что мы от него ожидаем. Когда базовая запись не заблокирована, она возвращает объект за миллисекунды; когда он заблокирован, он возвращает объект, описывающий заблокированный статус записи.
Но когда базовая запись действительно заблокирована, требуется более 15 секунд, чтобы вернуться с ожидаемой «ОШИБКОЙ [HY000] [DataDirect] [ODBC Progress OpenEdge Wire Protocol driver] [OPENEDGE] Не удалось получить блокировку записи для записи из таблицы PUB.i -мст."
Я попытался уменьшить значение CommandTimeout, но только это (в конце концов, поскольку я уменьшаю его постепенно) в конечном итоге меняет сбой на ошибку тайм-аута.
Есть ли какой-либо параметр более низкого уровня для управления тем, сколько времени требуется ODBC или OpenEdge для ожидания освобождения блокировки перед сбоем?
Вот код:
public static dynamic ReadOdbcForEdit(OdbcConnection connection, string type, string criteria, string domain,
string parentClass, string application)
{
connection.Open();
var transaction = connection.BeginTransaction(IsolationLevel.ReadCommitted);
Type objectType = Object.GetJohnstonType(parentClass + type, domain, application);
var tempObj = Activator.CreateInstance(objectType);
try
{
var odbcCommand = new OdbcCommand(criteria)
{
Connection = connection,
Transaction = transaction,
CommandTimeout = 30
};
var reader = odbcCommand.ExecuteReader();
while (reader.Read())
{
foreach (var property in tempObj.GetType().GetProperties())
{
var propertyType = property.PropertyType;
var propertyName = property.Name;
if (propertyType.IsArray ||
propertyType.IsGenericType &&
propertyType.GetGenericTypeDefinition() == typeof(List<>))
{
continue;
}
try
{
if (reader[propertyName].GetType() != typeof(DBNull))
{
property.SetValue(tempObj, reader[propertyName]);
}
}
catch (Exception e)
{
Logging.Message($"Could not fill {propertyName} from database column");
Logging.Exception(e);
}
}
}
return tempObj;
}
catch (Exception e)
{
var openRecordStatus = new OpenRecordStatus
{
StatusCode = e.HResult,
StatusMessage = e.Message
};
return openRecordStatus;
}
}