From 23b82a39212aa93643925f7f8ff64040e9998edd Mon Sep 17 00:00:00 2001 From: Kyle Bradley Date: Wed, 16 Oct 2024 18:46:03 +0100 Subject: [PATCH] Add support for EntityFramework --- EventFlow.sln | 17 +++ .../ClearFlow.ValueObjects.Dtos.csproj | 2 +- .../ClearFlow.ValueObjects.csproj | 2 +- .../EntityFrameworkTestExtensions.cs | 3 +- .../EventFlow.EntityFramework.Tests.csproj | 42 ++++-- .../InMemory/EfInMemoryEventStoreTests.cs | 17 ++- .../InMemory/EfInMemoryReadStoreTests.cs | 15 +- .../InMemory/EfInMemorySnapshotTests.cs | 16 ++- .../InMemory/InMemoryDbContextProvider.cs | 1 + .../Infrastructure/IndexingInMemoryTable.cs | 29 ++-- .../IndexingInMemoryTableFactory.cs | 7 +- .../Model/ThingyMessageReadModelEntity.cs | 10 +- .../Model/ThingyReadModelEntity.cs | 23 +-- .../MsSql/EfMsSqlEventStoreTests.cs | 19 +-- .../MsSql/EfMsSqlReadStoreIncludeTests.cs | 17 ++- .../MsSql/EfMsSqlReadStoreTests.cs | 16 ++- .../MsSql/EfMsSqlSnapshotTests.cs | 17 ++- .../ReadModels/PersonReadModelEntity.cs | 12 +- .../PostgreSql/EfPostgreSqlEventStoreTests.cs | 19 +-- .../PostgreSql/EfPostgreSqlReadStoreTests.cs | 16 ++- .../PostgreSql/EfPostgreSqlSnapshotTests.cs | 20 +-- .../SQLite/EfInMemorySnapshotTests.cs | 15 +- .../SQLite/EfSqliteEventStoreTests.cs | 15 +- .../SQLite/EfSqliteReadStoreTests.cs | 15 +- .../EntityFrameworkConfiguration.cs | 17 +-- .../EventFlow.EntityFramework.csproj | 51 +++---- .../EntityFrameworkEventPersistence.cs | 124 ++++++++-------- ...ionsEntityFrameworkEventStoreExtensions.cs | 38 +++++ ...entFlowOptionsEntityFrameworkExtensions.cs | 134 +----------------- ...tionsEntityFrameworkReadStoreExtensions.cs | 102 +++++++++++++ ...ptionsEntityFrameworkSnapshotExtensions.cs | 40 ++++++ .../IEntityFrameworkConfiguration.cs | 4 +- .../EntityFrameworkReadModelStore.cs | 16 +-- .../EventFlow.EventStore.csproj | 2 +- .../EventFlow.Hangfire.csproj | 2 +- .../ReadStores/MongoDbReadModelStoreTests.cs | 2 +- .../EventFlow.MongoDB.csproj | 2 +- .../EventFlow.PostgreSql.csproj | 19 ++- .../EventFlow.RabbitMQ.csproj | 2 +- Source/EventFlow.Sql/EventFlow.Sql.csproj | 8 +- Source/EventFlow/EventFlow.csproj | 6 +- 41 files changed, 558 insertions(+), 376 deletions(-) create mode 100644 Source/EventFlow.EntityFramework/Extensions/EventFlowOptionsEntityFrameworkEventStoreExtensions.cs create mode 100644 Source/EventFlow.EntityFramework/Extensions/EventFlowOptionsEntityFrameworkReadStoreExtensions.cs create mode 100644 Source/EventFlow.EntityFramework/Extensions/EventFlowOptionsEntityFrameworkSnapshotExtensions.cs diff --git a/EventFlow.sln b/EventFlow.sln index 58b4860ff..67336a03a 100644 --- a/EventFlow.sln +++ b/EventFlow.sln @@ -69,6 +69,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventFlow.PostgreSql", "Sou EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventFlow.PostgreSql.Tests", "Source\EventFlow.PostgreSql.Tests\EventFlow.PostgreSql.Tests.csproj", "{472095E5-7233-48AE-BBEA-56199F83707E}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "EntityFramework", "EntityFramework", "{EF3D7E6F-1AB6-4B84-83C4-21D1F49EDF45}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventFlow.EntityFramework", "Source\EventFlow.EntityFramework\EventFlow.EntityFramework.csproj", "{97A911C0-EBBB-45B0-8B84-065A5CC72368}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventFlow.EntityFramework.Tests", "Source\EventFlow.EntityFramework.Tests\EventFlow.EntityFramework.Tests.csproj", "{FDA8C3EE-82C1-4D72-A82C-2F76F53DD6F8}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -159,6 +165,14 @@ Global {472095E5-7233-48AE-BBEA-56199F83707E}.Debug|Any CPU.Build.0 = Debug|Any CPU {472095E5-7233-48AE-BBEA-56199F83707E}.Release|Any CPU.ActiveCfg = Release|Any CPU {472095E5-7233-48AE-BBEA-56199F83707E}.Release|Any CPU.Build.0 = Release|Any CPU + {97A911C0-EBBB-45B0-8B84-065A5CC72368}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {97A911C0-EBBB-45B0-8B84-065A5CC72368}.Debug|Any CPU.Build.0 = Debug|Any CPU + {97A911C0-EBBB-45B0-8B84-065A5CC72368}.Release|Any CPU.ActiveCfg = Release|Any CPU + {97A911C0-EBBB-45B0-8B84-065A5CC72368}.Release|Any CPU.Build.0 = Release|Any CPU + {FDA8C3EE-82C1-4D72-A82C-2F76F53DD6F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FDA8C3EE-82C1-4D72-A82C-2F76F53DD6F8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FDA8C3EE-82C1-4D72-A82C-2F76F53DD6F8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FDA8C3EE-82C1-4D72-A82C-2F76F53DD6F8}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -192,6 +206,9 @@ Global {F8484014-DA21-4388-B74A-2D90108656E8} = {31881D2B-26BB-4EF5-B29A-800731368C21} {E8B07B33-DBF1-4C9F-9C18-8825C3595FA4} = {3A68BD5F-FE8D-4CD4-A039-3EFBDEDE8865} {472095E5-7233-48AE-BBEA-56199F83707E} = {3A68BD5F-FE8D-4CD4-A039-3EFBDEDE8865} + {EF3D7E6F-1AB6-4B84-83C4-21D1F49EDF45} = {5EE323DE-E69B-451A-8AC3-22DD6A004FBA} + {97A911C0-EBBB-45B0-8B84-065A5CC72368} = {EF3D7E6F-1AB6-4B84-83C4-21D1F49EDF45} + {FDA8C3EE-82C1-4D72-A82C-2F76F53DD6F8} = {EF3D7E6F-1AB6-4B84-83C4-21D1F49EDF45} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {17607E2C-4E8E-45A2-85BD-0A5808E1C0F3} diff --git a/Source/ClearFlow.ValueObjects.Dtos/ClearFlow.ValueObjects.Dtos.csproj b/Source/ClearFlow.ValueObjects.Dtos/ClearFlow.ValueObjects.Dtos.csproj index 776f02d38..d2345705e 100644 --- a/Source/ClearFlow.ValueObjects.Dtos/ClearFlow.ValueObjects.Dtos.csproj +++ b/Source/ClearFlow.ValueObjects.Dtos/ClearFlow.ValueObjects.Dtos.csproj @@ -8,7 +8,7 @@ Data transfer objects (DTOs) for ClearFlow's Value Objects CQRS ES event sourcing Dtos Initial release for basic value objects. - 0.1.1 + 0.1.3 true enable diff --git a/Source/ClearFlow.ValueObjects/ClearFlow.ValueObjects.csproj b/Source/ClearFlow.ValueObjects/ClearFlow.ValueObjects.csproj index 138270a20..980994c5b 100644 --- a/Source/ClearFlow.ValueObjects/ClearFlow.ValueObjects.csproj +++ b/Source/ClearFlow.ValueObjects/ClearFlow.ValueObjects.csproj @@ -8,7 +8,7 @@ Common value objects available with ClearFlow CQRS ES event sourcing value objects Initial release for basic value objects. - 0.1.1 + 0.1.3 true enable diff --git a/Source/EventFlow.EntityFramework.Tests/EntityFrameworkTestExtensions.cs b/Source/EventFlow.EntityFramework.Tests/EntityFrameworkTestExtensions.cs index 0c05e5855..df12bc351 100644 --- a/Source/EventFlow.EntityFramework.Tests/EntityFrameworkTestExtensions.cs +++ b/Source/EventFlow.EntityFramework.Tests/EntityFrameworkTestExtensions.cs @@ -26,6 +26,7 @@ using EventFlow.EntityFramework.Tests.MsSql.IncludeTests.ReadModels; using EventFlow.Extensions; using EventFlow.TestHelpers.Aggregates.Entities; +using Microsoft.Extensions.DependencyInjection; namespace EventFlow.EntityFramework.Tests { @@ -46,7 +47,7 @@ public static IEventFlowOptions ConfigureForSnapshotStoreTest(this IEventFlowOpt public static IEventFlowOptions ConfigureForReadStoreTest(this IEventFlowOptions options) { return options - .RegisterServices(sr => sr.RegisterType(typeof(ThingyMessageLocator))) + .RegisterServices(sr => sr.AddTransient(typeof(ThingyMessageLocator))) .UseEntityFrameworkReadModel() .UseEntityFrameworkReadModel() .AddQueryHandlers( diff --git a/Source/EventFlow.EntityFramework.Tests/EventFlow.EntityFramework.Tests.csproj b/Source/EventFlow.EntityFramework.Tests/EventFlow.EntityFramework.Tests.csproj index 6f293aba1..0a8020123 100644 --- a/Source/EventFlow.EntityFramework.Tests/EventFlow.EntityFramework.Tests.csproj +++ b/Source/EventFlow.EntityFramework.Tests/EventFlow.EntityFramework.Tests.csproj @@ -1,26 +1,38 @@  - netcoreapp3.1 + net6.0;net7.0;net8.0 False - - - - - - - - + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/EventFlow.EntityFramework.Tests/InMemory/EfInMemoryEventStoreTests.cs b/Source/EventFlow.EntityFramework.Tests/InMemory/EfInMemoryEventStoreTests.cs index 008c7fa49..49a19ff5f 100644 --- a/Source/EventFlow.EntityFramework.Tests/InMemory/EfInMemoryEventStoreTests.cs +++ b/Source/EventFlow.EntityFramework.Tests/InMemory/EfInMemoryEventStoreTests.cs @@ -20,12 +20,12 @@ // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -using System.Threading.Tasks; -using EventFlow.Configuration; +using System; using EventFlow.EntityFramework.Extensions; using EventFlow.EntityFramework.Tests.Model; using EventFlow.TestHelpers; using EventFlow.TestHelpers.Suites; +using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; namespace EventFlow.EntityFramework.Tests.InMemory @@ -33,13 +33,16 @@ namespace EventFlow.EntityFramework.Tests.InMemory [Category(Categories.Integration)] public class EfInMemoryEventStoreTests : TestSuiteForEventStore { - protected override IRootResolver CreateRootResolver(IEventFlowOptions eventFlowOptions) + protected override IServiceProvider Configure(IEventFlowOptions eventFlowOptions) { - return eventFlowOptions + var resolver = eventFlowOptions .ConfigureEntityFramework(EntityFrameworkConfiguration.New) - .AddDbContextProvider(Lifetime.Singleton) - .ConfigureForEventStoreTest() - .CreateResolver(); + .AddDbContextProvider(ServiceLifetime.Singleton) + .ConfigureForEventStoreTest(); + + var serviceProvider = base.Configure(resolver); + + return serviceProvider; } } } \ No newline at end of file diff --git a/Source/EventFlow.EntityFramework.Tests/InMemory/EfInMemoryReadStoreTests.cs b/Source/EventFlow.EntityFramework.Tests/InMemory/EfInMemoryReadStoreTests.cs index f733df91e..c5193aa76 100644 --- a/Source/EventFlow.EntityFramework.Tests/InMemory/EfInMemoryReadStoreTests.cs +++ b/Source/EventFlow.EntityFramework.Tests/InMemory/EfInMemoryReadStoreTests.cs @@ -21,11 +21,11 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. using System; -using EventFlow.Configuration; using EventFlow.EntityFramework.Extensions; using EventFlow.EntityFramework.Tests.Model; using EventFlow.TestHelpers; using EventFlow.TestHelpers.Suites; +using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; namespace EventFlow.EntityFramework.Tests.InMemory @@ -35,13 +35,16 @@ public class EfInMemoryReadStoreTests : TestSuiteForReadModelStore { protected override Type ReadModelType => typeof(ThingyReadModelEntity); - protected override IRootResolver CreateRootResolver(IEventFlowOptions eventFlowOptions) + protected override IServiceProvider Configure(IEventFlowOptions eventFlowOptions) { - return eventFlowOptions + var resolver = eventFlowOptions .ConfigureEntityFramework(EntityFrameworkConfiguration.New) - .AddDbContextProvider(Lifetime.Singleton) - .ConfigureForReadStoreTest() - .CreateResolver(); + .AddDbContextProvider(ServiceLifetime.Singleton) + .ConfigureForReadStoreTest(); + + var serviceProvider = base.Configure(resolver); + + return serviceProvider; } } } \ No newline at end of file diff --git a/Source/EventFlow.EntityFramework.Tests/InMemory/EfInMemorySnapshotTests.cs b/Source/EventFlow.EntityFramework.Tests/InMemory/EfInMemorySnapshotTests.cs index a8ba38328..6bf8bbe80 100644 --- a/Source/EventFlow.EntityFramework.Tests/InMemory/EfInMemorySnapshotTests.cs +++ b/Source/EventFlow.EntityFramework.Tests/InMemory/EfInMemorySnapshotTests.cs @@ -20,25 +20,29 @@ // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -using EventFlow.Configuration; using EventFlow.EntityFramework.Extensions; using EventFlow.EntityFramework.Tests.Model; using EventFlow.TestHelpers; using EventFlow.TestHelpers.Suites; +using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; +using System; namespace EventFlow.EntityFramework.Tests.InMemory { [Category(Categories.Integration)] public class EfInMemorySnapshotTests : TestSuiteForSnapshotStore { - protected override IRootResolver CreateRootResolver(IEventFlowOptions eventFlowOptions) + protected override IServiceProvider Configure(IEventFlowOptions eventFlowOptions) { - return eventFlowOptions + var resolver = eventFlowOptions .ConfigureEntityFramework(EntityFrameworkConfiguration.New) - .AddDbContextProvider(Lifetime.Singleton) - .ConfigureForSnapshotStoreTest() - .CreateResolver(); + .AddDbContextProvider(ServiceLifetime.Singleton) + .ConfigureForSnapshotStoreTest(); + + var serviceProvider = base.Configure(resolver); + + return serviceProvider; } } } \ No newline at end of file diff --git a/Source/EventFlow.EntityFramework.Tests/InMemory/InMemoryDbContextProvider.cs b/Source/EventFlow.EntityFramework.Tests/InMemory/InMemoryDbContextProvider.cs index ccb864993..7d100284d 100644 --- a/Source/EventFlow.EntityFramework.Tests/InMemory/InMemoryDbContextProvider.cs +++ b/Source/EventFlow.EntityFramework.Tests/InMemory/InMemoryDbContextProvider.cs @@ -27,6 +27,7 @@ namespace EventFlow.EntityFramework.Tests.InMemory { + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "EF1001:Internal EF Core API usage.", Justification = "Only for test")] public class InMemoryDbContextProvider : IDbContextProvider { private readonly DbContextOptions _options; diff --git a/Source/EventFlow.EntityFramework.Tests/InMemory/Infrastructure/IndexingInMemoryTable.cs b/Source/EventFlow.EntityFramework.Tests/InMemory/Infrastructure/IndexingInMemoryTable.cs index 543deecd9..5ecd36806 100644 --- a/Source/EventFlow.EntityFramework.Tests/InMemory/Infrastructure/IndexingInMemoryTable.cs +++ b/Source/EventFlow.EntityFramework.Tests/InMemory/Infrastructure/IndexingInMemoryTable.cs @@ -25,6 +25,7 @@ using System.Collections.Generic; using System.Linq; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.InMemory.Storage.Internal; using Microsoft.EntityFrameworkCore.InMemory.ValueGeneration.Internal; using Microsoft.EntityFrameworkCore.Metadata; @@ -39,6 +40,12 @@ public class IndexingInMemoryTable : IInMemoryTable private readonly HashSet[] _indexes; private readonly IInMemoryTable _innerTable; + public IEnumerable Rows => _innerTable.Rows; + + public IInMemoryTable BaseTable => _innerTable; + + public IEntityType EntityType => throw new InvalidOperationException("Property deprecated in newer versions so not used anymore."); + public IndexingInMemoryTable(IInMemoryTable innerTable, IIndex[] indexDefinitions) { _innerTable = innerTable; @@ -51,8 +58,9 @@ public IReadOnlyList SnapshotRows() return _innerTable.SnapshotRows(); } - public void Create(IUpdateEntry entry) + public void Create(IUpdateEntry entry, IDiagnosticsLogger updateLogger) { + //_entityType = entry.EntityType; var indexEntries = _indexDefinitions .Select(d => d.Properties.Select(entry.GetCurrentValue).ToArray()) .Select(values => new IndexEntry(values)) @@ -61,24 +69,29 @@ public void Create(IUpdateEntry entry) if (indexEntries.Select((item, i) => _indexes[i].Contains(item)).Any(contains => contains)) throw new DbUpdateException("Error while updating.", new Exception("Unique constraint violated.")); - _innerTable.Create(entry); + _innerTable.Create(entry, updateLogger); indexEntries.Select((item, i) => _indexes[i].Add(item)).ToArray(); } - public void Delete(IUpdateEntry entry) + public void Delete(IUpdateEntry entry, IDiagnosticsLogger updateLogger) + { + _innerTable.Delete(entry, updateLogger); + } + + public void Update(IUpdateEntry entry, IDiagnosticsLogger updateLogger) { - _innerTable.Delete(entry); + _innerTable.Update(entry, updateLogger); } - public void Update(IUpdateEntry entry) + public InMemoryIntegerValueGenerator GetIntegerValueGenerator(IProperty property, IReadOnlyList tables) { - _innerTable.Update(entry); + return _innerTable.GetIntegerValueGenerator(property, tables); } - public InMemoryIntegerValueGenerator GetIntegerValueGenerator(IProperty property) + public void BumpValueGenerators(object[] row) { - return _innerTable.GetIntegerValueGenerator(property); + _innerTable.BumpValueGenerators(row); } private struct IndexEntry diff --git a/Source/EventFlow.EntityFramework.Tests/InMemory/Infrastructure/IndexingInMemoryTableFactory.cs b/Source/EventFlow.EntityFramework.Tests/InMemory/Infrastructure/IndexingInMemoryTableFactory.cs index 6549253b8..259681f36 100644 --- a/Source/EventFlow.EntityFramework.Tests/InMemory/Infrastructure/IndexingInMemoryTableFactory.cs +++ b/Source/EventFlow.EntityFramework.Tests/InMemory/Infrastructure/IndexingInMemoryTableFactory.cs @@ -22,6 +22,7 @@ using System.Linq; using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.InMemory.Infrastructure.Internal; using Microsoft.EntityFrameworkCore.InMemory.Storage.Internal; using Microsoft.EntityFrameworkCore.Metadata; @@ -30,13 +31,13 @@ namespace EventFlow.EntityFramework.Tests.InMemory.Infrastructure [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "EF1001:Internal EF Core API usage.", Justification = "Only for test")] public class IndexingInMemoryTableFactory : InMemoryTableFactory { - public IndexingInMemoryTableFactory(ILoggingOptions loggingOptions) : base(loggingOptions) + public IndexingInMemoryTableFactory(ILoggingOptions loggingOptions, IInMemorySingletonOptions options) : base(loggingOptions, options) { } - public override IInMemoryTable Create(IEntityType entityType) + public override IInMemoryTable Create(IEntityType entityType, IInMemoryTable baseTable) { - var innerTable = base.Create(entityType); + var innerTable = base.Create(entityType, baseTable); var uniqueIndexes = entityType.GetIndexes().Where(i => i.IsUnique).ToArray(); return uniqueIndexes.Any() diff --git a/Source/EventFlow.EntityFramework.Tests/Model/ThingyMessageReadModelEntity.cs b/Source/EventFlow.EntityFramework.Tests/Model/ThingyMessageReadModelEntity.cs index 54945118d..e5954f127 100644 --- a/Source/EventFlow.EntityFramework.Tests/Model/ThingyMessageReadModelEntity.cs +++ b/Source/EventFlow.EntityFramework.Tests/Model/ThingyMessageReadModelEntity.cs @@ -22,6 +22,8 @@ using System.ComponentModel.DataAnnotations; using System.Linq; +using System.Threading; +using System.Threading.Tasks; using EventFlow.Aggregates; using EventFlow.ReadStores; using EventFlow.TestHelpers.Aggregates; @@ -41,19 +43,23 @@ public class ThingyMessageReadModelEntity : IReadModel, public string Message { get; set; } - public void Apply(IReadModelContext context, IDomainEvent domainEvent) + public Task ApplyAsync(IReadModelContext context, IDomainEvent domainEvent, CancellationToken cancellationToken) { ThingyId = domainEvent.AggregateIdentity.Value; Message = domainEvent.AggregateEvent.ThingyMessage.Message; + + return Task.CompletedTask; } - public void Apply(IReadModelContext context, IDomainEvent domainEvent) + public Task ApplyAsync(IReadModelContext context, IDomainEvent domainEvent, CancellationToken cancellationToken) { ThingyId = domainEvent.AggregateIdentity.Value; var messageId = new ThingyMessageId(context.ReadModelId); var thingyMessage = domainEvent.AggregateEvent.ThingyMessages.Single(m => m.Id == messageId); Message = thingyMessage.Message; + + return Task.CompletedTask; } public ThingyMessage ToThingyMessage() diff --git a/Source/EventFlow.EntityFramework.Tests/Model/ThingyReadModelEntity.cs b/Source/EventFlow.EntityFramework.Tests/Model/ThingyReadModelEntity.cs index 7e898cc47..7610dcefb 100644 --- a/Source/EventFlow.EntityFramework.Tests/Model/ThingyReadModelEntity.cs +++ b/Source/EventFlow.EntityFramework.Tests/Model/ThingyReadModelEntity.cs @@ -21,6 +21,8 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. using System.ComponentModel.DataAnnotations; +using System.Threading; +using System.Threading.Tasks; using EventFlow.Aggregates; using EventFlow.ReadStores; using EventFlow.TestHelpers.Aggregates; @@ -42,22 +44,25 @@ public class ThingyReadModelEntity : IReadModel, [ConcurrencyCheck] public long Version { get; set; } - public void Apply(IReadModelContext context, - IDomainEvent domainEvent) + public Task ApplyAsync(IReadModelContext context, IDomainEvent domainEvent, CancellationToken cancellationToken) { - context.MarkForDeletion(); + DomainErrorAfterFirstReceived = true; + + return Task.CompletedTask; } - public void Apply(IReadModelContext context, - IDomainEvent domainEvent) + public Task ApplyAsync(IReadModelContext context, IDomainEvent domainEvent, CancellationToken cancellationToken) { - DomainErrorAfterFirstReceived = true; + PingsReceived++; + + return Task.CompletedTask; } - public void Apply(IReadModelContext context, - IDomainEvent domainEvent) + public Task ApplyAsync(IReadModelContext context, IDomainEvent domainEvent, CancellationToken cancellationToken) { - PingsReceived++; + context.MarkForDeletion(); + + return Task.CompletedTask; } public Thingy ToThingy() diff --git a/Source/EventFlow.EntityFramework.Tests/MsSql/EfMsSqlEventStoreTests.cs b/Source/EventFlow.EntityFramework.Tests/MsSql/EfMsSqlEventStoreTests.cs index ba5082871..831bd6486 100644 --- a/Source/EventFlow.EntityFramework.Tests/MsSql/EfMsSqlEventStoreTests.cs +++ b/Source/EventFlow.EntityFramework.Tests/MsSql/EfMsSqlEventStoreTests.cs @@ -20,14 +20,14 @@ // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -using System.Threading.Tasks; -using EventFlow.Configuration; +using System; using EventFlow.EntityFramework.Extensions; using EventFlow.EntityFramework.Tests.Model; using EventFlow.Extensions; using EventFlow.TestHelpers; using EventFlow.TestHelpers.MsSql; using EventFlow.TestHelpers.Suites; +using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; namespace EventFlow.EntityFramework.Tests.MsSql @@ -37,22 +37,25 @@ public class EfMsSqlEventStoreTests : TestSuiteForEventStore { private IMsSqlDatabase _testDatabase; - protected override IRootResolver CreateRootResolver(IEventFlowOptions eventFlowOptions) + protected override IServiceProvider Configure(IEventFlowOptions eventFlowOptions) { _testDatabase = MsSqlHelpz.CreateDatabase("eventflow"); - return eventFlowOptions - .RegisterServices(sr => sr.Register(c => _testDatabase.ConnectionString)) + var resolver = eventFlowOptions + .RegisterServices(sr => sr.AddTransient(c => _testDatabase.ConnectionString)) .ConfigureEntityFramework(EntityFrameworkConfiguration.New) .AddDbContextProvider() - .ConfigureForEventStoreTest() - .CreateResolver(); + .ConfigureForEventStoreTest(); + + var serviceProvider = base.Configure(resolver); + + return serviceProvider; } [TearDown] public void TearDown() { - _testDatabase.DisposeSafe("Failed to delete database"); + _testDatabase.DisposeSafe(Logger, "Failed to delete database"); } } } \ No newline at end of file diff --git a/Source/EventFlow.EntityFramework.Tests/MsSql/EfMsSqlReadStoreIncludeTests.cs b/Source/EventFlow.EntityFramework.Tests/MsSql/EfMsSqlReadStoreIncludeTests.cs index 01145608d..e9f0e69aa 100644 --- a/Source/EventFlow.EntityFramework.Tests/MsSql/EfMsSqlReadStoreIncludeTests.cs +++ b/Source/EventFlow.EntityFramework.Tests/MsSql/EfMsSqlReadStoreIncludeTests.cs @@ -20,6 +20,7 @@ // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +using System; using System.Threading; using System.Threading.Tasks; using EventFlow.Configuration; @@ -32,6 +33,7 @@ using EventFlow.TestHelpers; using EventFlow.TestHelpers.MsSql; using FluentAssertions; +using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; namespace EventFlow.EntityFramework.Tests.MsSql @@ -41,23 +43,26 @@ public class EfMsSqlReadStoreIncludeTests : IntegrationTest { private IMsSqlDatabase _testDatabase; - protected override IRootResolver CreateRootResolver(IEventFlowOptions eventFlowOptions) + protected override IServiceProvider Configure(IEventFlowOptions eventFlowOptions) { _testDatabase = MsSqlHelpz.CreateDatabase("eventflow"); - return eventFlowOptions - .RegisterServices(sr => sr.Register(c => _testDatabase.ConnectionString)) + var resolver = eventFlowOptions + .RegisterServices(sr => sr.AddTransient(c => _testDatabase.ConnectionString)) .ConfigureEntityFramework(EntityFrameworkConfiguration.New) .AddDbContextProvider() .ConfigureForReadStoreIncludeTest() - .AddDefaults(typeof(EfMsSqlReadStoreIncludeTests).Assembly) - .CreateResolver(); + .AddDefaults(typeof(EfMsSqlReadStoreIncludeTests).Assembly); + + var serviceProvider = base.Configure(resolver); + + return serviceProvider; } [TearDown] public void TearDown() { - _testDatabase.DisposeSafe("Failed to delete database"); + _testDatabase.DisposeSafe(Logger, "Failed to delete database"); } [Test] diff --git a/Source/EventFlow.EntityFramework.Tests/MsSql/EfMsSqlReadStoreTests.cs b/Source/EventFlow.EntityFramework.Tests/MsSql/EfMsSqlReadStoreTests.cs index ed7cda29c..7df4348b1 100644 --- a/Source/EventFlow.EntityFramework.Tests/MsSql/EfMsSqlReadStoreTests.cs +++ b/Source/EventFlow.EntityFramework.Tests/MsSql/EfMsSqlReadStoreTests.cs @@ -28,6 +28,7 @@ using EventFlow.TestHelpers; using EventFlow.TestHelpers.MsSql; using EventFlow.TestHelpers.Suites; +using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; namespace EventFlow.EntityFramework.Tests.MsSql @@ -39,22 +40,25 @@ public class EfMsSqlReadStoreTests : TestSuiteForReadModelStore protected override Type ReadModelType => typeof(ThingyReadModelEntity); - protected override IRootResolver CreateRootResolver(IEventFlowOptions eventFlowOptions) + protected override IServiceProvider Configure(IEventFlowOptions eventFlowOptions) { _testDatabase = MsSqlHelpz.CreateDatabase("eventflow"); - return eventFlowOptions - .RegisterServices(sr => sr.Register(c => _testDatabase.ConnectionString)) + var resolver = eventFlowOptions + .RegisterServices(sr => sr.AddTransient(c => _testDatabase.ConnectionString)) .ConfigureEntityFramework(EntityFrameworkConfiguration.New) .AddDbContextProvider() - .ConfigureForReadStoreTest() - .CreateResolver(); + .ConfigureForReadStoreTest(); + + var serviceProvider = base.Configure(resolver); + + return serviceProvider; } [TearDown] public void TearDown() { - _testDatabase.DisposeSafe("Failed to delete database"); + _testDatabase.DisposeSafe(Logger, "Failed to delete database"); } } } \ No newline at end of file diff --git a/Source/EventFlow.EntityFramework.Tests/MsSql/EfMsSqlSnapshotTests.cs b/Source/EventFlow.EntityFramework.Tests/MsSql/EfMsSqlSnapshotTests.cs index 38160af32..9dbe101c6 100644 --- a/Source/EventFlow.EntityFramework.Tests/MsSql/EfMsSqlSnapshotTests.cs +++ b/Source/EventFlow.EntityFramework.Tests/MsSql/EfMsSqlSnapshotTests.cs @@ -27,7 +27,9 @@ using EventFlow.TestHelpers; using EventFlow.TestHelpers.MsSql; using EventFlow.TestHelpers.Suites; +using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; +using System; namespace EventFlow.EntityFramework.Tests.MsSql { @@ -36,22 +38,25 @@ public class EfMsSqlSnapshotTests : TestSuiteForSnapshotStore { private IMsSqlDatabase _testDatabase; - protected override IRootResolver CreateRootResolver(IEventFlowOptions eventFlowOptions) + protected override IServiceProvider Configure(IEventFlowOptions eventFlowOptions) { _testDatabase = MsSqlHelpz.CreateDatabase("eventflow-snapshots"); - return eventFlowOptions - .RegisterServices(sr => sr.Register(c => _testDatabase.ConnectionString)) + var resolver = eventFlowOptions + .RegisterServices(sr => sr.AddTransient(c => _testDatabase.ConnectionString)) .ConfigureEntityFramework(EntityFrameworkConfiguration.New) .AddDbContextProvider() - .ConfigureForSnapshotStoreTest() - .CreateResolver(); + .ConfigureForSnapshotStoreTest(); + + var serviceProvider = base.Configure(resolver); + + return serviceProvider; } [TearDown] public void TearDown() { - _testDatabase.DisposeSafe("Failed to delete database"); + _testDatabase.DisposeSafe(Logger, "Failed to delete database"); } } } \ No newline at end of file diff --git a/Source/EventFlow.EntityFramework.Tests/MsSql/IncludeTests/ReadModels/PersonReadModelEntity.cs b/Source/EventFlow.EntityFramework.Tests/MsSql/IncludeTests/ReadModels/PersonReadModelEntity.cs index 8681d278f..eb86ce690 100644 --- a/Source/EventFlow.EntityFramework.Tests/MsSql/IncludeTests/ReadModels/PersonReadModelEntity.cs +++ b/Source/EventFlow.EntityFramework.Tests/MsSql/IncludeTests/ReadModels/PersonReadModelEntity.cs @@ -23,6 +23,8 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; +using System.Threading; +using System.Threading.Tasks; using EventFlow.Aggregates; using EventFlow.EntityFramework.Tests.MsSql.IncludeTests.Events; using EventFlow.ReadStores; @@ -43,14 +45,14 @@ public class PersonReadModelEntity : IReadModel, public virtual ICollection Addresses { get; set; } = new List(); - public void Apply(IReadModelContext context, - IDomainEvent domainEvent) + public Task ApplyAsync(IReadModelContext context, IDomainEvent domainEvent, CancellationToken cancellationToken) { Name = domainEvent.AggregateEvent.Name; + + return Task.CompletedTask; } - public void Apply(IReadModelContext context, - IDomainEvent domainEvent) + public Task ApplyAsync(IReadModelContext context, IDomainEvent domainEvent, CancellationToken cancellationToken) { var address = domainEvent.AggregateEvent.Address; Addresses.Add(new AddressReadModelEntity @@ -64,6 +66,8 @@ public void Apply(IReadModelContext context, }); NumberOfAddresses = Addresses.Count; + + return Task.CompletedTask; } public Person ToPerson() => diff --git a/Source/EventFlow.EntityFramework.Tests/PostgreSql/EfPostgreSqlEventStoreTests.cs b/Source/EventFlow.EntityFramework.Tests/PostgreSql/EfPostgreSqlEventStoreTests.cs index f37fdb891..e7fcdf722 100644 --- a/Source/EventFlow.EntityFramework.Tests/PostgreSql/EfPostgreSqlEventStoreTests.cs +++ b/Source/EventFlow.EntityFramework.Tests/PostgreSql/EfPostgreSqlEventStoreTests.cs @@ -20,14 +20,14 @@ // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -using System.Threading.Tasks; -using EventFlow.Configuration; +using System; using EventFlow.EntityFramework.Extensions; using EventFlow.EntityFramework.Tests.Model; using EventFlow.Extensions; using EventFlow.PostgreSql.TestsHelpers; using EventFlow.TestHelpers; using EventFlow.TestHelpers.Suites; +using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; namespace EventFlow.EntityFramework.Tests.PostgreSql @@ -37,22 +37,25 @@ public class EfPostgreSqlEventStoreTests : TestSuiteForEventStore { private IPostgreSqlDatabase _testDatabase; - protected override IRootResolver CreateRootResolver(IEventFlowOptions eventFlowOptions) + protected override IServiceProvider Configure(IEventFlowOptions eventFlowOptions) { _testDatabase = PostgreSqlHelpz.CreateDatabase("eventflow"); - return eventFlowOptions - .RegisterServices(sr => sr.Register(c => _testDatabase.ConnectionString)) + var resolver = eventFlowOptions + .RegisterServices(sr => sr.AddTransient(c => _testDatabase.ConnectionString)) .ConfigureEntityFramework(EntityFrameworkConfiguration.New) .AddDbContextProvider() - .ConfigureForEventStoreTest() - .CreateResolver(); + .ConfigureForEventStoreTest(); + + var serviceProvider = base.Configure(resolver); + + return serviceProvider; } [TearDown] public void TearDown() { - _testDatabase.DisposeSafe("Failed to delete database"); + _testDatabase.DisposeSafe(Logger, "Failed to delete database"); } } } \ No newline at end of file diff --git a/Source/EventFlow.EntityFramework.Tests/PostgreSql/EfPostgreSqlReadStoreTests.cs b/Source/EventFlow.EntityFramework.Tests/PostgreSql/EfPostgreSqlReadStoreTests.cs index 4c0ea99f9..d7d48bdd4 100644 --- a/Source/EventFlow.EntityFramework.Tests/PostgreSql/EfPostgreSqlReadStoreTests.cs +++ b/Source/EventFlow.EntityFramework.Tests/PostgreSql/EfPostgreSqlReadStoreTests.cs @@ -28,6 +28,7 @@ using EventFlow.PostgreSql.TestsHelpers; using EventFlow.TestHelpers; using EventFlow.TestHelpers.Suites; +using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; namespace EventFlow.EntityFramework.Tests.PostgreSql @@ -39,22 +40,25 @@ public class EfPostgreSqlReadStoreTests : TestSuiteForReadModelStore protected override Type ReadModelType => typeof(ThingyReadModelEntity); - protected override IRootResolver CreateRootResolver(IEventFlowOptions eventFlowOptions) + protected override IServiceProvider Configure(IEventFlowOptions eventFlowOptions) { _testDatabase = PostgreSqlHelpz.CreateDatabase("eventflow"); - return eventFlowOptions - .RegisterServices(sr => sr.Register(c => _testDatabase.ConnectionString)) + var resolver = eventFlowOptions + .RegisterServices(sr => sr.AddTransient(c => _testDatabase.ConnectionString)) .ConfigureEntityFramework(EntityFrameworkConfiguration.New) .AddDbContextProvider() - .ConfigureForReadStoreTest() - .CreateResolver(); + .ConfigureForReadStoreTest(); + + var serviceProvider = base.Configure(resolver); + + return serviceProvider; } [TearDown] public void TearDown() { - _testDatabase.DisposeSafe("Failed to delete database"); + _testDatabase.DisposeSafe(Logger, "Failed to delete database"); } } } \ No newline at end of file diff --git a/Source/EventFlow.EntityFramework.Tests/PostgreSql/EfPostgreSqlSnapshotTests.cs b/Source/EventFlow.EntityFramework.Tests/PostgreSql/EfPostgreSqlSnapshotTests.cs index b345fe391..a8c7ed40e 100644 --- a/Source/EventFlow.EntityFramework.Tests/PostgreSql/EfPostgreSqlSnapshotTests.cs +++ b/Source/EventFlow.EntityFramework.Tests/PostgreSql/EfPostgreSqlSnapshotTests.cs @@ -20,14 +20,15 @@ // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -using EventFlow.Configuration; using EventFlow.EntityFramework.Extensions; using EventFlow.EntityFramework.Tests.Model; using EventFlow.Extensions; using EventFlow.PostgreSql.TestsHelpers; using EventFlow.TestHelpers; using EventFlow.TestHelpers.Suites; +using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; +using System; namespace EventFlow.EntityFramework.Tests.PostgreSql { @@ -36,22 +37,25 @@ public class EfPostgreSqlSnapshotTests : TestSuiteForSnapshotStore { private IPostgreSqlDatabase _testDatabase; - protected override IRootResolver CreateRootResolver(IEventFlowOptions eventFlowOptions) + protected override IServiceProvider Configure(IEventFlowOptions eventFlowOptions) { - _testDatabase = PostgreSqlHelpz.CreateDatabase("eventflow-snapshots"); + _testDatabase = PostgreSqlHelpz.CreateDatabase("snapshots"); - return eventFlowOptions - .RegisterServices(sr => sr.Register(c => _testDatabase.ConnectionString)) + var resolver = eventFlowOptions + .RegisterServices(sr => sr.AddTransient(c => _testDatabase.ConnectionString)) .ConfigureEntityFramework(EntityFrameworkConfiguration.New) .AddDbContextProvider() - .ConfigureForSnapshotStoreTest() - .CreateResolver(); + .ConfigureForSnapshotStoreTest(); + + var serviceProvider = base.Configure(resolver); + + return serviceProvider; } [TearDown] public void TearDown() { - _testDatabase.DisposeSafe("Failed to delete database"); + _testDatabase.DisposeSafe(Logger, "Failed to delete database"); } } } \ No newline at end of file diff --git a/Source/EventFlow.EntityFramework.Tests/SQLite/EfInMemorySnapshotTests.cs b/Source/EventFlow.EntityFramework.Tests/SQLite/EfInMemorySnapshotTests.cs index af01c86d5..5f88ade36 100644 --- a/Source/EventFlow.EntityFramework.Tests/SQLite/EfInMemorySnapshotTests.cs +++ b/Source/EventFlow.EntityFramework.Tests/SQLite/EfInMemorySnapshotTests.cs @@ -25,20 +25,25 @@ using EventFlow.EntityFramework.Tests.Model; using EventFlow.TestHelpers; using EventFlow.TestHelpers.Suites; +using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; +using System; namespace EventFlow.EntityFramework.Tests.SQLite { [Category(Categories.Integration)] public class EfSqliteSnapshotTests : TestSuiteForSnapshotStore { - protected override IRootResolver CreateRootResolver(IEventFlowOptions eventFlowOptions) + protected override IServiceProvider Configure(IEventFlowOptions eventFlowOptions) { - return eventFlowOptions + var resolver = eventFlowOptions .ConfigureEntityFramework(EntityFrameworkConfiguration.New) - .AddDbContextProvider(Lifetime.Singleton) - .ConfigureForSnapshotStoreTest() - .CreateResolver(); + .AddDbContextProvider(ServiceLifetime.Singleton) + .ConfigureForSnapshotStoreTest(); + + var serviceProvider = base.Configure(resolver); + + return serviceProvider; } } } \ No newline at end of file diff --git a/Source/EventFlow.EntityFramework.Tests/SQLite/EfSqliteEventStoreTests.cs b/Source/EventFlow.EntityFramework.Tests/SQLite/EfSqliteEventStoreTests.cs index fe71a6bb1..df14caecb 100644 --- a/Source/EventFlow.EntityFramework.Tests/SQLite/EfSqliteEventStoreTests.cs +++ b/Source/EventFlow.EntityFramework.Tests/SQLite/EfSqliteEventStoreTests.cs @@ -20,12 +20,14 @@ // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +using System; using System.Threading.Tasks; using EventFlow.Configuration; using EventFlow.EntityFramework.Extensions; using EventFlow.EntityFramework.Tests.Model; using EventFlow.TestHelpers; using EventFlow.TestHelpers.Suites; +using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; namespace EventFlow.EntityFramework.Tests.SQLite @@ -33,13 +35,16 @@ namespace EventFlow.EntityFramework.Tests.SQLite [Category(Categories.Integration)] public class EfSqliteEventStoreTests : TestSuiteForEventStore { - protected override IRootResolver CreateRootResolver(IEventFlowOptions eventFlowOptions) + protected override IServiceProvider Configure(IEventFlowOptions eventFlowOptions) { - return eventFlowOptions + var resolver = eventFlowOptions .ConfigureEntityFramework(EntityFrameworkConfiguration.New) - .AddDbContextProvider(Lifetime.Singleton) - .ConfigureForEventStoreTest() - .CreateResolver(); + .AddDbContextProvider(ServiceLifetime.Singleton) + .ConfigureForEventStoreTest(); + + var serviceProvider = base.Configure(resolver); + + return serviceProvider; } } } \ No newline at end of file diff --git a/Source/EventFlow.EntityFramework.Tests/SQLite/EfSqliteReadStoreTests.cs b/Source/EventFlow.EntityFramework.Tests/SQLite/EfSqliteReadStoreTests.cs index 195dbc2b6..48098cd8f 100644 --- a/Source/EventFlow.EntityFramework.Tests/SQLite/EfSqliteReadStoreTests.cs +++ b/Source/EventFlow.EntityFramework.Tests/SQLite/EfSqliteReadStoreTests.cs @@ -21,11 +21,11 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. using System; -using EventFlow.Configuration; using EventFlow.EntityFramework.Extensions; using EventFlow.EntityFramework.Tests.Model; using EventFlow.TestHelpers; using EventFlow.TestHelpers.Suites; +using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; namespace EventFlow.EntityFramework.Tests.SQLite @@ -35,13 +35,16 @@ public class EfSqliteReadStoreTests : TestSuiteForReadModelStore { protected override Type ReadModelType => typeof(ThingyReadModelEntity); - protected override IRootResolver CreateRootResolver(IEventFlowOptions eventFlowOptions) + protected override IServiceProvider Configure(IEventFlowOptions eventFlowOptions) { - return eventFlowOptions + var resolver = eventFlowOptions .ConfigureEntityFramework(EntityFrameworkConfiguration.New) - .AddDbContextProvider(Lifetime.Singleton) - .ConfigureForReadStoreTest() - .CreateResolver(); + .AddDbContextProvider(ServiceLifetime.Singleton) + .ConfigureForReadStoreTest(); + + var serviceProvider = base.Configure(resolver); + + return serviceProvider; } } } \ No newline at end of file diff --git a/Source/EventFlow.EntityFramework/EntityFrameworkConfiguration.cs b/Source/EventFlow.EntityFramework/EntityFrameworkConfiguration.cs index 2d42c7e08..ff683fd55 100644 --- a/Source/EventFlow.EntityFramework/EntityFrameworkConfiguration.cs +++ b/Source/EventFlow.EntityFramework/EntityFrameworkConfiguration.cs @@ -22,13 +22,14 @@ using System; using EventFlow.Configuration; +using Microsoft.Extensions.DependencyInjection; namespace EventFlow.EntityFramework { public class EntityFrameworkConfiguration : IEntityFrameworkConfiguration { - private Action _registerUniqueConstraintDetectionStrategy; - private Action _registerBulkOperationConfiguration; + private Action _registerUniqueConstraintDetectionStrategy; + private Action _registerBulkOperationConfiguration; public static EntityFrameworkConfiguration New => new EntityFrameworkConfiguration(); @@ -38,24 +39,24 @@ private EntityFrameworkConfiguration() UseBulkOperationConfiguration(); } - void IEntityFrameworkConfiguration.Apply(IServiceRegistration serviceRegistration) + void IEntityFrameworkConfiguration.Apply(IServiceCollection serviceCollection) { - serviceRegistration.Register(s => this); - _registerUniqueConstraintDetectionStrategy(serviceRegistration); - _registerBulkOperationConfiguration(serviceRegistration); + serviceCollection.AddTransient(s => this); + _registerUniqueConstraintDetectionStrategy(serviceCollection); + _registerBulkOperationConfiguration(serviceCollection); } public EntityFrameworkConfiguration UseBulkOperationConfiguration() where T : class, IBulkOperationConfiguration { - _registerBulkOperationConfiguration = s => s.Register(); + _registerBulkOperationConfiguration = s => s.AddTransient(); return this; } public EntityFrameworkConfiguration UseUniqueConstraintDetectionStrategy() where T : class, IUniqueConstraintDetectionStrategy { - _registerUniqueConstraintDetectionStrategy = s => s.Register(); + _registerUniqueConstraintDetectionStrategy = s => s.AddTransient(); return this; } } diff --git a/Source/EventFlow.EntityFramework/EventFlow.EntityFramework.csproj b/Source/EventFlow.EntityFramework/EventFlow.EntityFramework.csproj index 4a67c176c..7bf88d21e 100644 --- a/Source/EventFlow.EntityFramework/EventFlow.EntityFramework.csproj +++ b/Source/EventFlow.EntityFramework/EventFlow.EntityFramework.csproj @@ -1,42 +1,37 @@  - - netstandard2.0;netcoreapp3.1 - True - True - False - True - EventFlow.EntityFramework - Frank Ebersoll - Rasmus Mikkelsen + net6.0;net7.0;net8.0 + ClearFlow.EntityFramework + ClearFlow.EntityFramework + Kyle Bradley, Frank Ebersoll + Kyle Bradley Copyright (c) Rasmus Mikkelsen 2015 - 2021 Entity Framework Core support for EventFlow CQRS ES event sourcing EF Entity Framework Core - git - https://github.com/eventflow/EventFlow - https://docs.geteventflow.net/ - MIT - en-US - UPDATED BY BUILD + Updated to include latest EventFlow + true + 0.1.3 + ClearFlow.EntityFramework + https://github.com/kyle-bradley/EventFlow + + + + - - - 3.1.5 - + + - + - 3.1.1 + 8.0.10 - - - - - - - + + + + 7.0.20 + diff --git a/Source/EventFlow.EntityFramework/EventStores/EntityFrameworkEventPersistence.cs b/Source/EventFlow.EntityFramework/EventStores/EntityFrameworkEventPersistence.cs index 11f42fea0..05fc5ffbc 100644 --- a/Source/EventFlow.EntityFramework/EventStores/EntityFrameworkEventPersistence.cs +++ b/Source/EventFlow.EntityFramework/EventStores/EntityFrameworkEventPersistence.cs @@ -30,8 +30,8 @@ using EventFlow.EntityFramework.Extensions; using EventFlow.EventStores; using EventFlow.Exceptions; -using EventFlow.Logs; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; namespace EventFlow.EntityFramework.EventStores { @@ -39,16 +39,16 @@ public class EntityFrameworkEventPersistence : IEventPersistence where TDbContext : DbContext { private readonly IDbContextProvider _contextProvider; - private readonly ILog _log; + private readonly ILogger> _logger; private readonly IUniqueConstraintDetectionStrategy _strategy; public EntityFrameworkEventPersistence( - ILog log, + ILogger> logger, IDbContextProvider contextProvider, IUniqueConstraintDetectionStrategy strategy ) { - _log = log; + _logger = logger; _contextProvider = contextProvider; _strategy = strategy; } @@ -60,29 +60,29 @@ public async Task LoadAllCommittedEvents(GlobalPosition ? 0 : long.Parse(globalPosition.Value); - using (var context = _contextProvider.CreateContext()) - { - var entities = await context - .Set() - .OrderBy(e => e.GlobalSequenceNumber) - .Where(e => e.GlobalSequenceNumber >= startPosition) - .Take(pageSize) - .ToListAsync(cancellationToken) - .ConfigureAwait(false); - - var nextPosition = entities.Any() - ? entities.Max(e => e.GlobalSequenceNumber) + 1 - : startPosition; - - return new AllCommittedEventsPage(new GlobalPosition(nextPosition.ToString()), entities); - } + await using var context = _contextProvider.CreateContext(); + + var entities = await context + .Set() + .OrderBy(e => e.GlobalSequenceNumber) + .Where(e => e.GlobalSequenceNumber >= startPosition) + .Take(pageSize) + .ToListAsync(cancellationToken); + + var nextPosition = entities.Any() + ? entities.Max(e => e.GlobalSequenceNumber) + 1 + : startPosition; + + return new AllCommittedEventsPage(new GlobalPosition(nextPosition.ToString()), entities); } public async Task> CommitEventsAsync(IIdentity id, IReadOnlyCollection serializedEvents, CancellationToken cancellationToken) { if (!serializedEvents.Any()) - return new ICommittedDomainEvent[0]; + { + return Array.Empty(); + } var entities = serializedEvents .Select((e, i) => new EventEntity @@ -96,24 +96,22 @@ public async Task> CommitEventsAsync( }) .ToList(); - _log.Verbose( - "Committing {0} events to EntityFramework event store for entity with ID '{1}'", + _logger.LogTrace( + "Committing {Count} events to EntityFramework event store for entity with ID '{Id}'", entities.Count, id); try { - using (var context = _contextProvider.CreateContext()) - { - await context.AddRangeAsync(entities, cancellationToken); - await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false); - } + await using var context = _contextProvider.CreateContext(); + await context.AddRangeAsync(entities, cancellationToken); + await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false); } catch (DbUpdateException ex) when (ex.IsUniqueConstraintViolation(_strategy)) { - _log.Verbose( + _logger.LogTrace( "Entity Framework event insert detected an optimistic concurrency " + - "exception for entity with ID '{0}'", id); + "exception for entity with ID '{Id}'", id); throw new OptimisticConcurrencyException(ex.Message, ex); } @@ -123,38 +121,48 @@ public async Task> CommitEventsAsync( public async Task> LoadCommittedEventsAsync(IIdentity id, int fromEventSequenceNumber, CancellationToken cancellationToken) { - using (var context = _contextProvider.CreateContext()) - { - var entities = await context - .Set() - .Where(e => e.AggregateId == id.Value - && e.AggregateSequenceNumber >= fromEventSequenceNumber) - .OrderBy(e => e.AggregateSequenceNumber) - .ToListAsync(cancellationToken) - .ConfigureAwait(false); - - return entities; - } + await using var context = _contextProvider.CreateContext(); + + var entities = await context + .Set() + .Where(e => e.AggregateId == id.Value + && e.AggregateSequenceNumber >= fromEventSequenceNumber) + .OrderBy(e => e.AggregateSequenceNumber) + .ToListAsync(cancellationToken); + + return entities; + } + + public async Task> LoadCommittedEventsAsync(IIdentity id, int fromEventSequenceNumber, int toEventSequenceNumber, CancellationToken cancellationToken) + { + await using var context = _contextProvider.CreateContext(); + + var entities = await context + .Set() + .Where(e => e.AggregateId == id.Value + && e.AggregateSequenceNumber >= fromEventSequenceNumber && e.AggregateSequenceNumber <= toEventSequenceNumber) + .OrderBy(e => e.AggregateSequenceNumber) + .ToListAsync(cancellationToken); + + return entities; } public async Task DeleteEventsAsync(IIdentity id, CancellationToken cancellationToken) { - using (var context = _contextProvider.CreateContext()) - { - var entities = await context.Set() - .Where(e => e.AggregateId == id.Value) - .Select(e => new EventEntity {GlobalSequenceNumber = e.GlobalSequenceNumber}) - .ToListAsync(cancellationToken) - .ConfigureAwait(false); - - context.RemoveRange(entities); - var rowsAffected = await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false); - - _log.Verbose( - "Deleted entity with ID '{0}' by deleting all of its {1} events", - id, - rowsAffected); - } + await using var context = _contextProvider.CreateContext(); + + var entities = await context.Set() + .Where(e => e.AggregateId == id.Value) + .Select(e => new EventEntity { GlobalSequenceNumber = e.GlobalSequenceNumber }) + .ToListAsync(cancellationToken); + + context.RemoveRange(entities); + var rowsAffected = await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false); + + _logger.LogTrace( + "Deleted entity with ID {Id} by deleting all of its {NumberOfEvents} events", + id, + rowsAffected); } } } \ No newline at end of file diff --git a/Source/EventFlow.EntityFramework/Extensions/EventFlowOptionsEntityFrameworkEventStoreExtensions.cs b/Source/EventFlow.EntityFramework/Extensions/EventFlowOptionsEntityFrameworkEventStoreExtensions.cs new file mode 100644 index 000000000..21b36e46d --- /dev/null +++ b/Source/EventFlow.EntityFramework/Extensions/EventFlowOptionsEntityFrameworkEventStoreExtensions.cs @@ -0,0 +1,38 @@ +// The MIT License (MIT) +// +// Copyright (c) 2015-2024 Rasmus Mikkelsen +// https://github.com/eventflow/EventFlow +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using EventFlow.EntityFramework.EventStores; +using EventFlow.Extensions; +using Microsoft.EntityFrameworkCore; + +namespace EventFlow.EntityFramework.Extensions +{ + public static class EventFlowOptionsEntityFrameworkEventStoreExtensions + { + public static IEventFlowOptions UseEntityFrameworkEventStore( + this IEventFlowOptions eventFlowOptions) + where TDbContext : DbContext + { + return eventFlowOptions.UseEventPersistence>(); + } + } +} \ No newline at end of file diff --git a/Source/EventFlow.EntityFramework/Extensions/EventFlowOptionsEntityFrameworkExtensions.cs b/Source/EventFlow.EntityFramework/Extensions/EventFlowOptionsEntityFrameworkExtensions.cs index e1b4129e7..aa128ef9c 100644 --- a/Source/EventFlow.EntityFramework/Extensions/EventFlowOptionsEntityFrameworkExtensions.cs +++ b/Source/EventFlow.EntityFramework/Extensions/EventFlowOptionsEntityFrameworkExtensions.cs @@ -21,15 +21,10 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. using System; -using EventFlow.Configuration; -using EventFlow.EntityFramework.EventStores; -using EventFlow.EntityFramework.ReadStores; -using EventFlow.EntityFramework.ReadStores.Configuration; -using EventFlow.EntityFramework.ReadStores.Configuration.Includes; -using EventFlow.EntityFramework.SnapshotStores; using EventFlow.Extensions; -using EventFlow.ReadStores; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; namespace EventFlow.EntityFramework.Extensions { @@ -43,134 +38,15 @@ public static IEventFlowOptions ConfigureEntityFramework( return eventFlowOptions.RegisterServices(configuration.Apply); } - public static IEventFlowOptions UseEntityFrameworkEventStore( - this IEventFlowOptions eventFlowOptions) - where TDbContext : DbContext - { - return eventFlowOptions - .UseEventStore>(); - } - - public static IEventFlowOptions UseEntityFrameworkSnapshotStore( - this IEventFlowOptions eventFlowOptions) - where TDbContext : DbContext - { - return eventFlowOptions - .UseSnapshotStore>(); - } - - public static IEventFlowOptions UseEntityFrameworkReadModel( - this IEventFlowOptions eventFlowOptions) - where TDbContext : DbContext - where TReadModel : class, IReadModel, new() - { - return eventFlowOptions - .RegisterServices(f => - { - f.Register, - EntityFrameworkReadModelStore>(); - f.Register>(_ => - new EntityFrameworkReadModelConfiguration(), Lifetime.Singleton); - f.Register>(r => - r.Resolver.Resolve>()); - }) - .UseReadStoreFor, TReadModel>(); - } - - /// - /// Configures the read model. Can be used for eager loading of related data by appending .Include(..) / .ThenInclude(..) statements. - /// - /// The read model's entity type - /// The database context type - /// - /// Function to configure eager loading of related data by appending .Include(..) / .ThenInclude(..) statements. - /// Avoid navigation properties if you create read models for both, the parent entity and the child entity. Otherwise there is a risk of a ordering problem when saving aggregates and updating read modules independently (FOREIGN-KEY constraint) - public static IEventFlowOptions UseEntityFrameworkReadModel( - this IEventFlowOptions eventFlowOptions, - Func,IApplyQueryableConfiguration> configure) - where TDbContext : DbContext - where TReadModel : class, IReadModel, new() - { - return eventFlowOptions - .RegisterServices(f => - { - f.Register, - EntityFrameworkReadModelStore>(); - f.Register(_ => - { - var readModelConfig = new EntityFrameworkReadModelConfiguration(); - return configure != null - ? configure(readModelConfig) - : readModelConfig; - - }, Lifetime.Singleton); - f.Register>(r => - r.Resolver.Resolve>()); - }) - .UseReadStoreFor, TReadModel>(); - } - - /// - /// Configures the read model. Can be used for eager loading of related data by appending .Include(..) / .ThenInclude(..) statements. - /// - /// The read model's entity type - /// The database context type - /// The read model locator type - /// - /// Function to configure eager loading of related data by appending .Include(..) / .ThenInclude(..) statements. - /// Avoid navigation properties if you create read models for both, the parent entity and the child entity. Otherwise there is a risk of a ordering problem when saving aggregates and updating read modules independently (FOREIGN-KEY constraint) - public static IEventFlowOptions UseEntityFrameworkReadModel( - this IEventFlowOptions eventFlowOptions, - Func,IApplyQueryableConfiguration> configure) - where TDbContext : DbContext - where TReadModel : class, IReadModel, new() - where TReadModelLocator : IReadModelLocator - { - return eventFlowOptions - .RegisterServices(f => - { - f.Register, - EntityFrameworkReadModelStore>(); - f.Register(_ => - { - var readModelConfig = new EntityFrameworkReadModelConfiguration(); - return configure != null - ? configure(readModelConfig) - : readModelConfig; - }, Lifetime.Singleton); - f.Register>(r => - r.Resolver.Resolve>()); - }) - .UseReadStoreFor, TReadModel, TReadModelLocator>(); - } - - public static IEventFlowOptions UseEntityFrameworkReadModel( - this IEventFlowOptions eventFlowOptions) - where TDbContext : DbContext - where TReadModel : class, IReadModel, new() - where TReadModelLocator : IReadModelLocator - { - return eventFlowOptions - .RegisterServices(f => - { - f.Register, - EntityFrameworkReadModelStore>(); - f.Register>(_ => - new EntityFrameworkReadModelConfiguration(), Lifetime.Singleton); - f.Register>(r => - r.Resolver.Resolve>()); - }) - .UseReadStoreFor, TReadModel, TReadModelLocator>(); - } public static IEventFlowOptions AddDbContextProvider( - this IEventFlowOptions eventFlowOptions, - Lifetime lifetime = Lifetime.AlwaysUnique) + this IEventFlowOptions eventFlowOptions, + ServiceLifetime serviceLifetime = ServiceLifetime.Transient) where TContextProvider : class, IDbContextProvider where TDbContext : DbContext { return eventFlowOptions.RegisterServices(s => - s.Register, TContextProvider>(lifetime)); + s.Replace(ServiceDescriptor.Describe(typeof(IDbContextProvider), typeof(TContextProvider), serviceLifetime))); } } } \ No newline at end of file diff --git a/Source/EventFlow.EntityFramework/Extensions/EventFlowOptionsEntityFrameworkReadStoreExtensions.cs b/Source/EventFlow.EntityFramework/Extensions/EventFlowOptionsEntityFrameworkReadStoreExtensions.cs new file mode 100644 index 000000000..dae8c2941 --- /dev/null +++ b/Source/EventFlow.EntityFramework/Extensions/EventFlowOptionsEntityFrameworkReadStoreExtensions.cs @@ -0,0 +1,102 @@ +// The MIT License (MIT) +// +// Copyright (c) 2015-2024 Rasmus Mikkelsen +// https://github.com/eventflow/EventFlow +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using System; +using EventFlow.EntityFramework.ReadStores; +using EventFlow.EntityFramework.ReadStores.Configuration; +using EventFlow.Extensions; +using EventFlow.ReadStores; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace EventFlow.EntityFramework.Extensions +{ + public static class EventFlowOptionsEntityFrameworkReadStoreExtensions + { + + private static IEventFlowOptions ApplyEntityFrameworkReadModelOptions(this IEventFlowOptions eventFlowOptions, + EntityFrameworkReadModelConfiguration config) + where TDbContext : DbContext + where TReadModel : class, IReadModel, new() + { + return eventFlowOptions + .RegisterServices(f => + { + f.TryAddTransient, + EntityFrameworkReadModelStore>(); + + f.TryAddSingleton>(_ => config); + + f.TryAddTransient>(r => + r.GetRequiredService>()); + }); + } + + public static IEventFlowOptions UseEntityFrameworkReadModel( + this IEventFlowOptions eventFlowOptions) + where TDbContext : DbContext + where TReadModel : class, IReadModel, new() + { + return eventFlowOptions.ApplyEntityFrameworkReadModelOptions(new EntityFrameworkReadModelConfiguration()) + .UseReadStoreFor, TReadModel>(); + } + + public static IEventFlowOptions UseEntityFrameworkReadModel( + this IEventFlowOptions eventFlowOptions, + Func, IApplyQueryableConfiguration> configure) + where TDbContext : DbContext + where TReadModel : class, IReadModel, new() + { + var readModelConfig = new EntityFrameworkReadModelConfiguration(); + configure(readModelConfig); + + return eventFlowOptions.ApplyEntityFrameworkReadModelOptions(readModelConfig) + .UseReadStoreFor, TReadModel>(); + } + + public static IEventFlowOptions UseEntityFrameworkReadModel( + this IEventFlowOptions eventFlowOptions, + Func, IApplyQueryableConfiguration> configure) + where TDbContext : DbContext + where TReadModel : class, IReadModel, new() + where TReadModelLocator : IReadModelLocator + { + var readModelConfig = new EntityFrameworkReadModelConfiguration(); + configure(readModelConfig); + + return eventFlowOptions.ApplyEntityFrameworkReadModelOptions(readModelConfig) + .UseReadStoreFor, TReadModel, TReadModelLocator>(); + } + + public static IEventFlowOptions UseEntityFrameworkReadModel( + this IEventFlowOptions eventFlowOptions) + where TDbContext : DbContext + where TReadModel : class, IReadModel, new() + where TReadModelLocator : IReadModelLocator + { + return eventFlowOptions.ApplyEntityFrameworkReadModelOptions(new EntityFrameworkReadModelConfiguration()) + .UseReadStoreFor, TReadModel, TReadModelLocator>(); + } + + } +} \ No newline at end of file diff --git a/Source/EventFlow.EntityFramework/Extensions/EventFlowOptionsEntityFrameworkSnapshotExtensions.cs b/Source/EventFlow.EntityFramework/Extensions/EventFlowOptionsEntityFrameworkSnapshotExtensions.cs new file mode 100644 index 000000000..74ad1f50e --- /dev/null +++ b/Source/EventFlow.EntityFramework/Extensions/EventFlowOptionsEntityFrameworkSnapshotExtensions.cs @@ -0,0 +1,40 @@ +// The MIT License (MIT) +// +// Copyright (c) 2015-2024 Rasmus Mikkelsen +// https://github.com/eventflow/EventFlow +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using EventFlow.EntityFramework.SnapshotStores; +using EventFlow.Extensions; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; + +namespace EventFlow.EntityFramework.Extensions +{ + public static class EventFlowOptionsEntityFrameworkSnapshotExtensions + { + public static IEventFlowOptions UseEntityFrameworkSnapshotStore( + this IEventFlowOptions eventFlowOptions) + where TDbContext : DbContext + { + return eventFlowOptions + .UseSnapshotPersistence>(ServiceLifetime.Transient); + } + } +} \ No newline at end of file diff --git a/Source/EventFlow.EntityFramework/IEntityFrameworkConfiguration.cs b/Source/EventFlow.EntityFramework/IEntityFrameworkConfiguration.cs index d259f4a6a..e25cfec6a 100644 --- a/Source/EventFlow.EntityFramework/IEntityFrameworkConfiguration.cs +++ b/Source/EventFlow.EntityFramework/IEntityFrameworkConfiguration.cs @@ -20,12 +20,12 @@ // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -using EventFlow.Configuration; +using Microsoft.Extensions.DependencyInjection; namespace EventFlow.EntityFramework { public interface IEntityFrameworkConfiguration { - void Apply(IServiceRegistration serviceRegistration); + void Apply(IServiceCollection serviceCollection); } } \ No newline at end of file diff --git a/Source/EventFlow.EntityFramework/ReadStores/EntityFrameworkReadModelStore.cs b/Source/EventFlow.EntityFramework/ReadStores/EntityFrameworkReadModelStore.cs index 78bb44e80..beedd533a 100644 --- a/Source/EventFlow.EntityFramework/ReadStores/EntityFrameworkReadModelStore.cs +++ b/Source/EventFlow.EntityFramework/ReadStores/EntityFrameworkReadModelStore.cs @@ -33,11 +33,11 @@ using EventFlow.EntityFramework.ReadStores.Configuration; using EventFlow.Exceptions; using EventFlow.Extensions; -using EventFlow.Logs; using EventFlow.ReadStores; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.ChangeTracking; using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.Extensions.Logging; namespace EventFlow.EntityFramework.ReadStores { @@ -60,12 +60,12 @@ private static readonly ConcurrentDictionary Descripto public EntityFrameworkReadModelStore( IBulkOperationConfiguration bulkOperationConfiguration, - ILog log, + ILogger> _logger, IReadModelFactory readModelFactory, IApplyQueryableConfiguration queryableConfiguration, IDbContextProvider contextProvider, ITransientFaultHandler transientFaultHandler) - : base(log) + : base(_logger) { _readModelFactory = readModelFactory; _queryableConfiguration = queryableConfiguration; @@ -152,7 +152,7 @@ public override async Task DeleteAllAsync(CancellationToken cancellationToken) }) .ConfigureAwait(false); - Log.Verbose( + Logger.LogTrace( "Purge {0} read models of type '{1}'", rowsAffected, readModelName); @@ -170,14 +170,14 @@ private async Task> GetAsync(TDbContext dbContext, if (entity == null) { - Log.Verbose(() => $"Could not find any Entity Framework read model '{readModelType.PrettyPrint()}' with ID '{id}'"); + Logger.LogTrace($"Could not find any Entity Framework read model '{readModelType.PrettyPrint()}' with ID '{id}'"); return ReadModelEnvelope.Empty(id); } var entry = dbContext.Entry(entity); var version = descriptor.GetVersion(entry); - Log.Verbose(() => $"Found Entity Framework read model '{readModelType.PrettyPrint()}' with ID '{id}' and version '{version}'"); + Logger.LogTrace($"Found Entity Framework read model '{readModelType.PrettyPrint()}' with ID '{id}' and version '{version}'"); return version.HasValue ? ReadModelEnvelope.With(id, entity, version.Value) @@ -194,7 +194,7 @@ private async Task DeleteAsync(TDbContext dbContext, string id, CancellationToke if (rowsAffected != 0) { - Log.Verbose($"Deleted Entity Framework read model '{id}' of type '{ReadModelNameLowerCase}'"); + Logger.LogTrace($"Deleted Entity Framework read model '{id}' of type '{ReadModelNameLowerCase}'"); } } @@ -255,7 +255,7 @@ private async Task UpdateReadModelAsync(TDbContext dbContext, IReadModelContextF throw new OptimisticConcurrencyException(e.Message, e); } - Log.Verbose(() => $"Updated Entity Framework read model {typeof(TReadModel).PrettyPrint()} with ID '{readModelId}' to version '{readModelEnvelope.Version}'"); + Logger.LogTrace($"Updated Entity Framework read model {typeof(TReadModel).PrettyPrint()} with ID '{readModelId}' to version '{readModelEnvelope.Version}'"); } private static EntityDescriptor GetDescriptor( diff --git a/Source/EventFlow.EventStore/EventFlow.EventStore.csproj b/Source/EventFlow.EventStore/EventFlow.EventStore.csproj index c0b0cef3a..ea2a0eed7 100644 --- a/Source/EventFlow.EventStore/EventFlow.EventStore.csproj +++ b/Source/EventFlow.EventStore/EventFlow.EventStore.csproj @@ -10,7 +10,7 @@ CQRS ES event sourcing EventStore Updated to include latest EventFlow changes along with fixes to the rebuilder.& .net 8.0 true - 0.1.1 + 0.1.3 ClearFlow.EventStore https://github.com/kyle-bradley/EventFlow diff --git a/Source/EventFlow.Hangfire/EventFlow.Hangfire.csproj b/Source/EventFlow.Hangfire/EventFlow.Hangfire.csproj index 5f07a6435..27bcb824e 100644 --- a/Source/EventFlow.Hangfire/EventFlow.Hangfire.csproj +++ b/Source/EventFlow.Hangfire/EventFlow.Hangfire.csproj @@ -8,7 +8,7 @@ Hangfire job scheduling support for EventFlow CQRS ES event sourcing Hangfire Updated to include latest EventFlow changes. - 0.1.1 + 0.1.3 true diff --git a/Source/EventFlow.MongoDB.Tests/IntegrationTests/ReadStores/MongoDbReadModelStoreTests.cs b/Source/EventFlow.MongoDB.Tests/IntegrationTests/ReadStores/MongoDbReadModelStoreTests.cs index d1c8960ee..3f271cf84 100644 --- a/Source/EventFlow.MongoDB.Tests/IntegrationTests/ReadStores/MongoDbReadModelStoreTests.cs +++ b/Source/EventFlow.MongoDB.Tests/IntegrationTests/ReadStores/MongoDbReadModelStoreTests.cs @@ -65,7 +65,7 @@ protected override IServiceProvider Configure(IEventFlowOptions eventFlowOptions typeof(MongoDbThingyGetWithLinqQueryHandler) ); - var serviceProvider = base.Configure(eventFlowOptions); + var serviceProvider = base.Configure(resolver); return serviceProvider; } diff --git a/Source/EventFlow.MongoDB/EventFlow.MongoDB.csproj b/Source/EventFlow.MongoDB/EventFlow.MongoDB.csproj index 0d702f5b6..b764d3281 100644 --- a/Source/EventFlow.MongoDB/EventFlow.MongoDB.csproj +++ b/Source/EventFlow.MongoDB/EventFlow.MongoDB.csproj @@ -7,7 +7,7 @@ MongoDB ReadStore and Snapshot Persistence for EventFlow CQRS ES event sourcing MongoDB UPDATED BY BUILD - 0.1.1 + 0.1.3 true diff --git a/Source/EventFlow.PostgreSql/EventFlow.PostgreSql.csproj b/Source/EventFlow.PostgreSql/EventFlow.PostgreSql.csproj index fa76b8a67..b4b02e842 100644 --- a/Source/EventFlow.PostgreSql/EventFlow.PostgreSql.csproj +++ b/Source/EventFlow.PostgreSql/EventFlow.PostgreSql.csproj @@ -1,14 +1,16 @@  net6.0;net7.0;net8.0 - EventFlow.PostgreSql - Rida Messaoudene - Rasmus Mikkelsen + ClearFlow.PostgreSql + ClearFlow.PostgreSql + Kyle Bradley, Rida Messaoudene + Kyle Bradley Copyright (c) Rasmus Mikkelsen 2015 - 2021 POSTGRESQL support for EventFlow CQRS ES event sourcing POSTGRESQL en-US UPDATED BY BUILD + 0.1.3.1 true @@ -26,10 +28,17 @@ - - + + + + + + + + + diff --git a/Source/EventFlow.RabbitMQ/EventFlow.RabbitMQ.csproj b/Source/EventFlow.RabbitMQ/EventFlow.RabbitMQ.csproj index 8bacf6cac..ec4d59b44 100644 --- a/Source/EventFlow.RabbitMQ/EventFlow.RabbitMQ.csproj +++ b/Source/EventFlow.RabbitMQ/EventFlow.RabbitMQ.csproj @@ -9,7 +9,7 @@ RabbitMQ integration for EventFlow CQRS ES event sourcing MongoDB Updated to include latest EventFlow changes. - 0.1.1 + 0.1.3 true diff --git a/Source/EventFlow.Sql/EventFlow.Sql.csproj b/Source/EventFlow.Sql/EventFlow.Sql.csproj index e76470c1e..b0781059d 100644 --- a/Source/EventFlow.Sql/EventFlow.Sql.csproj +++ b/Source/EventFlow.Sql/EventFlow.Sql.csproj @@ -1,13 +1,15 @@  net6.0;net7.0;net8.0; - EventFlow.Sql - Rasmus Mikkelsen - Rasmus Mikkelsen + ClearFlow.Sql + ClearFlow.Sql + Kyle Bradley, Rasmus Mikkelsen + Kyle Bradley, Rasmus Mikkelsen Copyright (c) Rasmus Mikkelsen 2015 - 2021 Generic SQL support for EventFlow CQRS ES event sourcing SQL UPDATED BY BUILD + 0.1.3 true diff --git a/Source/EventFlow/EventFlow.csproj b/Source/EventFlow/EventFlow.csproj index 93cd0170f..a973fc0be 100644 --- a/Source/EventFlow/EventFlow.csproj +++ b/Source/EventFlow/EventFlow.csproj @@ -9,7 +9,7 @@ Async/await first CQRS+ES and DDD framework for .NET - https://docs.geteventflow Updated to include latest EventFlow changes.& .net 8.0 bin\$(Configuration)\$(TargetFramework)\EventFlow.xml true - 0.1.1 + 0.1.3 Kyle Bradley, Rasmus Mikkelsen Kyle Bradley ClearFlow @@ -34,8 +34,8 @@ Async/await first CQRS+ES and DDD framework for .NET - https://docs.geteventflow - - + +