ServiceStack OrmLite Select 带更新锁
ServiceStack OrmLite Select with update lock
我有以下代码:
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");
var currentId = (int)idProperty.GetValue(item);
if (currentId != 0)
{
throw new ApplicationException("Cannot insert or update with non-zero ID");
}
var existingItem = connection.Select(singleItemPredicate).SingleOrDefault();
if (existingItem == null)
{
Insert(connection, item);
return;
}
var existingId = (int)idProperty.GetValue(existingItem);
idProperty.SetValue(item, existingId);
var affectedRowCount = connection.UpdateOnly(item, onlyFields: updateOnlyFields, where: singleItemPredicate);
if (affectedRowCount != 1)
{
throw new ApplicationException("Update failed");
}
}
但是使用默认隔离级别,这可能会导致多个线程在同一个 table 上工作时出错。
我想要的是 select-row
来指定我想要更新锁,例如:
var existingItem = connection.Select(singleItemPredicate).WithUpdateLock().SingleOrDefault();
- 对于SQL服务器,这将在末尾添加WITH UPDLOCK
SELECT行
我如何在 ServiceStack OrmLite 中最好地解决这个问题?
您可以使用 new SqlExpression SQL Filter just added in v4.5.5 that's now (available on MyGet) 自定义生成的 SQL 然后执行自定义的 Typed SqlExpression,例如:
var q = connection.From<T>()
.Where(singleItemPredicate)
.WithSqlFilter(sql => sql + " WITH UPDLOCK");
var existingItem = connection.Select(q).SingleOrDefault();
if (existingItem == null)
{
connection.Insert(item);
return;
}
我有以下代码:
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");
var currentId = (int)idProperty.GetValue(item);
if (currentId != 0)
{
throw new ApplicationException("Cannot insert or update with non-zero ID");
}
var existingItem = connection.Select(singleItemPredicate).SingleOrDefault();
if (existingItem == null)
{
Insert(connection, item);
return;
}
var existingId = (int)idProperty.GetValue(existingItem);
idProperty.SetValue(item, existingId);
var affectedRowCount = connection.UpdateOnly(item, onlyFields: updateOnlyFields, where: singleItemPredicate);
if (affectedRowCount != 1)
{
throw new ApplicationException("Update failed");
}
}
但是使用默认隔离级别,这可能会导致多个线程在同一个 table 上工作时出错。
我想要的是 select-row
来指定我想要更新锁,例如:
var existingItem = connection.Select(singleItemPredicate).WithUpdateLock().SingleOrDefault();
- 对于SQL服务器,这将在末尾添加WITH UPDLOCK SELECT行
我如何在 ServiceStack OrmLite 中最好地解决这个问题?
您可以使用 new SqlExpression SQL Filter just added in v4.5.5 that's now (available on MyGet) 自定义生成的 SQL 然后执行自定义的 Typed SqlExpression,例如:
var q = connection.From<T>()
.Where(singleItemPredicate)
.WithSqlFilter(sql => sql + " WITH UPDLOCK");
var existingItem = connection.Select(q).SingleOrDefault();
if (existingItem == null)
{
connection.Insert(item);
return;
}