add optimistic concurrency

This commit is contained in:
meysamhadeli 2022-06-12 23:05:23 +04:30
parent ed931ae0f2
commit 3d3f46f0b1
8 changed files with 73 additions and 25 deletions

View File

@ -25,9 +25,7 @@ namespace BuildingBlocks.Domain.Model
return dequeuedEvents;
}
public virtual void When(object @event) { }
public long Version { get; protected set; } = -1;
public long Version { get; set; } = -1;
public TId Id { get; protected set; }
}

View File

@ -1,19 +1,15 @@
using BuildingBlocks.Domain.Event;
using BuildingBlocks.EventStoreDB.Events;
using BuildingBlocks.Domain.Event;
namespace BuildingBlocks.Domain.Model
namespace BuildingBlocks.Domain.Model;
public interface IAggregate : IEntity
{
public interface IAggregate : IProjection, IEntity
{
IReadOnlyList<IDomainEvent> DomainEvents { get; }
IEvent[] ClearDomainEvents();
long Version { get; }
}
public interface IAggregate<out T> : IAggregate
{
T Id { get; }
}
IReadOnlyList<IDomainEvent> DomainEvents { get; }
IEvent[] ClearDomainEvents();
long Version { get; set; }
}
public interface IAggregate<out T> : IAggregate
{
T Id { get; }
}

View File

@ -111,11 +111,13 @@ public abstract class AppDbContextBase : DbContext, IDbContext
case EntityState.Added:
entry.Entity.CreatedBy = userId;
entry.Entity.CreatedAt = DateTime.Now;
entry.Entity.Version++;
break;
case EntityState.Modified:
entry.Entity.LastModifiedBy = userId;
entry.Entity.LastModified = DateTime.Now;
entry.Entity.Version++;
break;
case EntityState.Deleted:

View File

@ -0,0 +1,32 @@
using BuildingBlocks.Domain.Event;
using BuildingBlocks.Domain.Model;
namespace BuildingBlocks.EventStoreDB.Events
{
public abstract class AggregateEventSourcing<TId> : Entity, IAggregateEventSourcing<TId>
{
private readonly List<IDomainEvent> _domainEvents = new();
public IReadOnlyList<IDomainEvent> DomainEvents => _domainEvents.AsReadOnly();
public void AddDomainEvent(IDomainEvent domainEvent)
{
_domainEvents.Add(domainEvent);
}
public IEvent[] ClearDomainEvents()
{
IEvent[] dequeuedEvents = _domainEvents.ToArray();
_domainEvents.Clear();
return dequeuedEvents;
}
public virtual void When(object @event) { }
public long Version { get; protected set; } = -1;
public TId Id { get; protected set; }
}
}

View File

@ -0,0 +1,19 @@
using BuildingBlocks.Domain.Event;
using BuildingBlocks.Domain.Model;
namespace BuildingBlocks.EventStoreDB.Events
{
public interface IAggregateEventSourcing : IProjection, IEntity
{
IReadOnlyList<IDomainEvent> DomainEvents { get; }
IEvent[] ClearDomainEvents();
long Version { get; }
}
public interface IAggregateEventSourcing<out T> : IAggregateEventSourcing
{
T Id { get; }
}
}

View File

@ -1,11 +1,10 @@
using BuildingBlocks.Domain.Model;
using BuildingBlocks.EventStoreDB.Events;
using BuildingBlocks.EventStoreDB.Events;
using BuildingBlocks.EventStoreDB.Serialization;
using EventStore.Client;
namespace BuildingBlocks.EventStoreDB.Repository;
public interface IEventStoreDBRepository<T> where T : class, IAggregate<long>
public interface IEventStoreDBRepository<T> where T : class, IAggregateEventSourcing<long>
{
Task<T?> Find(long id, CancellationToken cancellationToken);
Task<ulong> Add(T aggregate, CancellationToken cancellationToken);
@ -13,7 +12,7 @@ public interface IEventStoreDBRepository<T> where T : class, IAggregate<long>
Task<ulong> Delete(T aggregate, long? expectedRevision = null, CancellationToken cancellationToken = default);
}
public class EventStoreDBRepository<T>: IEventStoreDBRepository<T> where T : class, IAggregate<long>
public class EventStoreDBRepository<T>: IEventStoreDBRepository<T> where T : class, IAggregateEventSourcing<long>
{
private readonly EventStoreClient eventStore;

View File

@ -1,4 +1,5 @@
using BuildingBlocks.Domain.Model;
using BuildingBlocks.EventStoreDB.Events;
using BuildingBlocks.Exception;
namespace BuildingBlocks.EventStoreDB.Repository;
@ -9,7 +10,7 @@ public static class RepositoryExtensions
this IEventStoreDBRepository<T> repository,
long id,
CancellationToken cancellationToken
) where T : class, IAggregate<long>
) where T : class, IAggregateEventSourcing<long>
{
var entity = await repository.Find(id, cancellationToken);
@ -22,7 +23,7 @@ public static class RepositoryExtensions
Action<T> action,
long? expectedVersion = null,
CancellationToken cancellationToken = default
) where T : class, IAggregate<long>
) where T : class, IAggregateEventSourcing<long>
{
var entity = await repository.Get(id, cancellationToken);

View File

@ -1,10 +1,11 @@
using Booking.Booking.Events.Domain;
using Booking.Booking.Models.ValueObjects;
using BuildingBlocks.Domain.Model;
using BuildingBlocks.EventStoreDB.Events;
namespace Booking.Booking.Models;
public class Booking : Aggregate<long>
public class Booking : AggregateEventSourcing<long>
{
public Booking()
{