У нас есть проблема, которая возникает при каждом вызове метода в течение ограниченных периодов времени. Тогда это работает как ожидалось. Проблема в том, что в коде создаются двойные предложения WHERE.
Мы используем Servicestack 4.5.14
Метод, который мы имеем:
protected static void InsertOrUpdate<T>(
IDbConnection connection,
T item,
Expression<Func<T, bool>> singleItemPredicate,
Expression<Func<T, object>> updateOnlyFields = null)
{
var type = item.GetType();
var idProperty = type.GetProperty("Id");
if (idProperty == null)
{
throw new Exception("Cannot insert or update on a class with no ID property");
}
var currentId = (int)idProperty.GetValue(item);
if (currentId != 0)
{
throw new Exception("Cannot insert or update with non-zero ID");
}
var query = connection.From<T>().Where(singleItemPredicate).WithSqlFilter(WithUpdateLock);
T existingItem;
try
{
existingItem = connection.Select(query).SingleOrDefault();
Log.Verbose(connection.GetLastSql);
}
catch (SqlException)
{
Log.Verbose(connection.GetLastSql);
throw;
}
if (existingItem == null)
{
Insert(connection, item);
return;
}
var existingId = (int)idProperty.GetValue(existingItem);
idProperty.SetValue(item, existingId);
try
{
var affectedRowCount = connection.UpdateOnly(item, onlyFields: updateOnlyFields, where: singleItemPredicate);
Log.Verbose(connection.GetLastSql);
if (affectedRowCount != 1)
{
throw new SwToolsException("Update failed");
}
}
catch (SqlException)
{
Log.Verbose(connection.GetLastSql);
throw;
}
}
Когда все это работает, пример вывода из журналов может быть:
ВЫБЕРИТЕ «Id», «Приложение», «Имя хоста», «LastContact», «Версия», «ToolState», «ServerState»
ОТ "ca". "ExecutionHost"
WITH (UPDLOCK) WHERE ("Имя хоста" = @ 0)
ОБНОВЛЕНИЕ "ca". "ExecutionHost" SET "LastContact" = @ LastContact, "Version" = @ Version, "ToolState" = @ ToolState, "ServerState" = @ ServerState WHERE ("Hostname" = @ 0)
При сбое вывод (тот же сеанс, только через несколько секунд) был:
ВЫБЕРИТЕ «Id», «Приложение», «Имя хоста», «LastContact», «Версия», «ToolState», «ServerState»
ОТ "ca". "ExecutionHost"
WITH (UPDLOCK) WHERE ("Имя хоста" = @ 0)
ОБНОВЛЕНИЕ "ca". "ExecutionHost" SET "LastContact" = @ LastContact, "Version" = @ Version, "ToolState" = @ ToolState, "ServerState" = @ ServerState ГДЕ "LastContact" = @ LastContact, "Version" = @ Version, "ToolState" = @ ToolState, "ServerState" = @ ServerState WHERE ("Имя хоста" = @ 0)
Жирным шрифтом выделено дополнение к SQL, которое делает вызов неудачным. Кажется, что он добавляет дополнительное предложение WHERE с содержимым из предложения SET.
Мы уже некоторое время отлаживали это, и на самом деле не знаем, находится ли проблема на «нашей» стороне или в Servicetack.
Есть идеи, где продолжить?