2016-07-19 15 views
0

Ich habe einen Dienst, der als Parameter ProcessOrdersArgs nimmt, die Tausende von Order-Objekten enthalten kann. Ich muss für einen Datenbankserver überprüfen, dass jeder übergebene Auftrag ein tatsächlich gültiger Auftrag ist, der vorhanden ist. Für einen einzigen Serviceaufruf, der Tausende von Bestellungen verarbeitet, mache ich gerade tausende von Rundreisen zur Datenbank, um die übergebenen Bestellungen zu validieren, und ich möchte die Anzahl der Datenbank-Rundreisen zur Validierung erheblich reduzieren.Wie kann die Erfassung von IDs gegen eine Datenbank oder eine externe Datenquelle effizient validiert werden?

Ich habe die folgenden relevanten Klassen für meine Validierungen. .CustomerId und .OrderId in meinem OrderValidator sind Erweiterungen der FluentValidation PropertyValidator-Klasse.

CustomerIdValidator hat Caching eingebaut, weil oft Tausende von Bestellungen verarbeitet werden, viele sind für den gleichen Kunden und ich möchte Rundreisen in die Datenbank bei der Validierung der gleichen CustomerId schneiden.

Ich möchte etwas ähnliches mit OrderIds machen und die Anzahl der Datenbank Roundtrips begrenzen, aber Caching ist nicht die Lösung, da jede OrderId der möglichen Tausende einzigartig sein wird. Ich möchte diese Bestell-IDs in großen Mengen validieren. Meine Idee ist es, die Liste der OrderIds für jeden Client zu kopieren und eine Liste ungültiger OrderIds (falls vorhanden) zurückzugeben, die als Validierungsfehler gemeldet werden.

Wie kann ich dies tun, oder muss ich meine Validierungen anders strukturieren, damit ich Aufträge in großen Mengen validieren kann, anstatt tausende Rundreise-Datenbankaufrufe zu tätigen?

public class Order 
{ 
    public int CustomerId { get; set; } 
    public int OrderId { get; set; } 
} 

public class ProcessOrdersArgs 
{ 
    public List<Order> Orders { get; set; } 
} 

public class ProcessOrdersArgsValidator : AbstractValidator<ProcessOrdersArgs> 
{ 
    public ProcessOrdersArgsValidator(OrderValidator orderValidator) 
    { 
     RuleFor(a => a.Orders) 
      .SetCollectionValidator(orderValidator); 
    } 
} 

public class OrderValidator : AbstractValidator<Order> 
{ 
    public OrderValidator(DBConnection dbConnection) 
    { 
     RuleFor(c => c.CustomerId) 
      .CustomerId(dbConnection); 

     RuleFor(c => c.OrderId) 
      .OrderId(dbConnection, c => c.CustomerId); 
    } 
} 
+0

Haben Sie die Daten in die Datenbank einfügen in Betracht ziehen? Sie könnten eine Tabelle mit einer Spalte und einem Fremdschlüssel erstellen, der auf die tatsächlichen in der Datenbank gespeicherten IDs verweist. Wenn die Einfügung fehlschlägt, befindet sich eine ungültige ID in Ihrer Datei. – PacoDePaco

+1

Ich kenne viele Möglichkeiten, eine Liste von IDs in einer Datenbank gegen eine Datenbank zu validieren. Das ist nicht der Punkt meiner Frage. Ich möchte verstehen, wie man das mit Fluent Validation macht. Mein Problem ist, dass mein Validierer der OrderId-Eigenschaft eine DB-Verbindung hat und jede OrderId einzeln validieren muss. Ich habe das Gefühl, dass ich diese Validierung bis zum ProcessOrdersArgsValidator selbst vorantreiben muss und die Validierung dort in großen Mengen durchführen muss, vielleicht indem ich eine ähnliche Methode anwende wie Sie oder etwas anderes. Dagegen bin ich mir nur nicht sicher, wie das mit Fluent Validation aussehen soll. – Dude0001

Antwort

1

können Sie predicate validatorMust oder MustAsync für Orders Eigenschaft

public class ProcessOrdersArgsValidator : AbstractValidator<ProcessOrdersArgs> 
{ 
    public ProcessOrdersArgsValidator(DBConnection dbConnection) 
    { 
     RuleFor(a => a.Orders).Must(orders => 
     { 
      var ids = orders.Select(o => o.OrderId); 

      return BulkValidateIds(ids, dbConnection); 
     }); 
    } 

    private bool BulkValidateIds(IEnumerable<int> ids, DBConnection dbConnection) 
    .... 
}