我们一直在使用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.
}));
}
}
但是,如您所见,它变得相当冗长。有没有更简单的方法来做到这一点?