1

我们一直在使用Dapper并且Dapper.Contrib可以轻松地执行常规数据库操作,这非常棒。但是,自从引入Polly为我们的某些操作添加重试策略以来,由于需要在执行重试之前检查记录的存在,我一直无法找到一种方法来保持同样的简单性。

这是我们当前如何执行插入的简化示例:

public async Task Insert(Payment payment)
{
    var retryPolicy = // Create using Polly.
    using (var connection = new SqlConnection(_connectionString))
    {
        var dao = MapToDao(payment);
        await retryPolicy.ExecuteAsync(() => connection.InsertAsync(dao));
    }
}

[Table("Payment")]
public class PaymentDao
{
    [ExplicitKey]
    public Guid PaymentId { get; set; }
    // A whole bunch of properties omitted for brevity
}

Payment我们的领域模型在哪里,PaymentDao是我们的数据访问对象。

实际上,我们在服务中确实有Insert明确检查重复项的调用逻辑,但这被重试策略否定了。这意味着自推出以来Polly,我们看到插入了少量重复付款。

我可以通过执行以下操作来解决此问题:

public async Task Insert(Payment payment)
{
    var retryPolicy = // Create using Polly.
    using (var connection = new SqlConnection(_connectionString))
    {
        var dao = MapToDao(payment);

        await retryPolicy.ExecuteAsync(() => connection.ExecuteAsync(
            @"IF ((SELECT COUNT(*) FROM dbo.Payment WHERE SubscriptionId = @subscriptionId) = 0)
            BEGIN
                INSERT INTO Payment
                (
                    PaymentId,
                    SubscriptionId,
                    // Lots of columns omitted for brevity.
                )
                VALUES
                (
                    @PaymentId,
                    @SubscriptionId,
                    // Lots of values omitted for brevity.
                )
            END",
            new
            {
                dao.PaymentId,
                dao.SubscriptionId,
                // Lots of properties omitted for brevity.
            }));
    }
}

但是,如您所见,它变得相当冗长。有没有更简单的方法来做到这一点?

4

1 回答 1

3

您可以考虑先使用模型检查然后执行插入的替代方法,因为搜索使用的参数较少

using (var connection = new SqlConnection(_connectionString)) {
    var dao = MapToDao(payment);
    var sql = "SELECT COUNT(1) FROM dbo.Payment WHERE SubscriptionId = @subscriptionId";
    await retryPolicy.ExecuteAsync(async () => { 
        var exists = await connection.ExecuteScalarAsync<bool>(sql, new {dao.SubscriptionId});
        if(!exists) {
            await connection.InsertAsync(dao);
        }
    });
}
于 2018-04-08T18:05:30.300 回答