2016-08-09 89 views
0

Ich habe ein PurchaseOrder-Aggregatstammverzeichnis mit zwei Methoden FinalizeOrder und CancellOrder, die beide Ereignisse aufzeichnen: OrderFinaziled und OrderCancelled. Ich stehe auf der Modellierung Auftrags Repository, kann ich diese Ereignisse innerhalb Repository-Muster zu aktualisieren Entität in der Datenbank? Ich werde nicht nach jeder Änderung, um ganze Aggregat root zu speichern, ich möchte nur das Feld, das geändert wurde, ich verwende SqlClient, keine ORMs speichern.Verwenden von Domain-Events zum Aktualisieren von Entitäten in Datenbank

meine Aggregate Wurzel Basisklasse:

public class AggregateRootBase<TID> : EntityBase<TID> 
{ 
    public AggregateRootBase(TID id) : base(id) 
    { 
    } 

    private readonly List<IDomainEvent> recordedEvents = new List<IDomainEvent>(); 

    public IEnumerable<IDomainEvent> GetEvents() 
    { 
     return recordedEvents; 
    } 
    public void MarkEventsAsProcessed() 
    { 
     recordedEvents.Clear(); 
    } 

    protected void RecordEvent(IDomainEvent @event) 
    { 
     recordedEvents.Add(@event); 
    } 
} 

PurchaseOrder Klasse (übersprungen die meisten Eigenschaften):

public class PurchaseOrder : AggregateRootBase<int> 
{ 
    public PurchaseOrder(int id) : base(id) 
    { 
     IsFinalized = false; 
     IsCancelled = false; 
    } 
    public bool IsFinalized { get; set; } 
    public bool IsCancelled { get; set; } 

    public void FinalizeOrder() 
    { 
     IsFinalized = true; 
     RecordEvent(new OrderFinalized(Id,IsFinalized)); 
    } 
    public void CancellOrder() 
    { 
     IsCancelled = true; 
     RecordEvent(new OrderCancelled(Id,IsCancelled)); 
    } 
} 

und Repository:

public class PurchaseOrderRepository 
{ 
    void Save(PurchaseOrder purchaseOrder) 
    { 
     var events = purchaseOrder.GetEvents(); 
     foreach (var evt in events) 
     { 
     if(evt.GetType() == typeof(OrderFinalized)) 
      // use event args and update field using SqlCommand 
     else if (evt.GetType() == typeof(OrderCancelled)) 
      // use event args and Update field Using SqlCommand 
     } 
    } 
} 

i, die auch einen Eventdispatcher haben Ereignisse Versendungen (E-Mail-Benachrichtigung) nach der erfolgreichen Persistenz von AggregateRoot.

Antwort

3

Wenn Sie Domain-Ereignisse verwenden möchten, um Ihre Änderungen zu speichern, sprechen Sie über projizieren Ereignisse in Ihrem Aggregatzustand. Es gibt einige Tools, die dabei helfen können. Was Sie versuchen zu tun, ähnelt dem Mustervergleich, ein übliches Merkmal der meisten funktionalen Sprachen. Um das Leben einfacher zu machen, möchten Sie vielleicht etwas wie Projac überprüfen. Wir verwenden es für Projektionen und es funktioniert sehr gut. Es hat auch SQL Server specific implementation.

Ein Beispiel, das Sie dort finden können:

public class PortfolioProjection : SqlProjection 
{ 
    public PortfolioProjection() 
    { 
    When<PortfolioAdded>(@event => 
     TSql.NonQueryStatement(
     "INSERT INTO [Portfolio] (Id, Name) VALUES (@P1, @P2)", 
     new { P1 = TSql.Int(@event.Id), P2 = TSql.NVarChar(@event.Name, 40) } 
    )); 

    When<PortfolioRemoved>(@event => 
     TSql.NonQueryStatement(
     "DELETE FROM [Portfolio] WHERE Id = @P1", 
     new { P1 = TSql.Int(@event.Id) } 
    )); 

    When<PortfolioRenamed>(@event => 
     TSql.NonQueryStatement(
     "UPDATE [Portfolio] SET Name = @P2 WHERE Id = @P1", 
     new { P1 = TSql.Int(@event.Id), P2 = TSql.NVarChar(@event.Name, 40) } 
    )); 
    } 
} 

Dann können Sie Projektor Instanz initialisieren:

_projector = new SqlProjector(
    Resolve.WhenEqualToHandlerMessageType(new PortfolioProjection()), 
    new TransactionalSqlCommandExecutor(
    new ConnectionStringSettings(
     "projac", 
     @"Data Source=(localdb)\ProjectsV12;Initial Catalog=ProjacUsage;Integrated Security=SSPI;", 
     "System.Data.SqlClient"), 
     IsolationLevel.ReadCommitted)); 

Und dann Projektveranstaltungen:

void Save(PurchaseOrder purchaseOrder) => 
    _projector.Project(purchaseOrder.GetEvents()); 

Sie könnten auch die überprüfen Ereignis-Sourcing-Muster, obwohl es ziemlich viel Komplexität hinzufügt.

+0

es sieht interessant aus, danke, ich werde es mir ansehen. – QuietNaN

+0

eine Frage über Ereignis Sourcing und Projektionen, verstehe ich richtig, dass, wenn ich Ereignisspeicher habe und wenn ich Domänenmodell aus Ereignis rekonstruiere, es Projektion ist, und auch wenn ich Ereignis verwende, um Aggregatzustand in der Datenbank zu aktualisieren, heißt es Projektion, ich bin neu zu DDD und CQRS und wenn ich etwas falsch verstanden habe, wenn es nicht hart ist, kannst du es aufräumen? – QuietNaN

+0

Sie müssen die Ereignisquelle nicht verwenden, um Projac zu verwenden. Sie führen nur Projektionen für Ihre Veranstaltungen durch. –