ServiceStack OrmLite选择更新锁定

时间:2017-01-19 10:11:02

标签: servicestack ormlite-servicestack

我有以下代码:

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");
    }
}

但是使用默认隔离级别,这可能会导致多个线程在同一个表上运行时出错。

我希望select-row指定我想要更新锁定,例如:

var existingItem = connection.Select(singleItemPredicate).WithUpdateLock().SingleOrDefault();
  • 对于SQL Server,这将在结尾处添加 WITH UPDLOCK SELECT行

我如何在ServiceStack OrmLite中最好地解决这个问题?

1 个答案:

答案 0 :(得分:1)

您可以使用现在的new SqlExpression SQL Filter just added in v4.5.5available 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;
}