Wir verwenden Dapper
und Dapper.Contrib
für die Leichtigkeit, mit der wir regelmäßige Datenbankoperationen durchführen können, was großartig war. Seit Einführung von Polly
zum Hinzufügen von Wiederholungsrichtlinien für einige unserer Operationen konnte ich jedoch keine Möglichkeit finden, die Einfachheit beizubehalten, da vor der Ausführung eines Wiederholungsversuchs nach der Existenz eines Datensatzes gesucht werden muss.
Hier ist ein vereinfachtes Beispiel dafür, wie wir derzeit Einsätze durchführen:
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
}
Wo Payment
unser Domain-Modell ist und PaymentDao
unser Datenzugriffsobjekt ist.
Wir haben tatsächlich eine Logik in dem Dienst, der Insert
aufruft, der explizit nach Duplikaten sucht, aber dies wird von der Wiederholungsrichtlinie negiert. Dies bedeutet, dass seit der Einführung von Polly
eine kleine Anzahl von doppelten Zahlungen eingefügt wird.
Ich kann das beheben, indem ich Folgendes tue:
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.
}));
}
}
Wie Sie jedoch sehen können, wird es ziemlich langatmig. Gibt es einen einfacheren Weg, dies zu tun?
Sie können die Alternative prüfen, zuerst das Modell zu verwenden und dann die Einfügung durchzuführen, da die Suche weniger Parameter verwendet
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);
}
});
}