Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v1: Convert Entity Framework #1076

Open
wants to merge 4 commits into
base: develop-v1
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
MMonrad marked this conversation as resolved.
Show resolved Hide resolved
Binary file not shown.
17 changes: 17 additions & 0 deletions EventFlow.sln
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventFlow.SQLite", "Source\
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventFlow.SQLite.Tests", "Source\EventFlow.SQLite.Tests\EventFlow.SQLite.Tests.csproj", "{8FAC191C-340D-47C6-B8AE-3D57783749C4}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "EntityFramework", "EntityFramework", "{21A29AA0-EF82-4717-89CE-729257C05C7D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventFlow.EntityFramework", "Source\EventFlow.EntityFramework\EventFlow.EntityFramework.csproj", "{ED4AA905-A208-4E67-8B40-CC8E1B8440B8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventFlow.EntityFramework.Tests", "Source\EventFlow.EntityFramework.Tests\EventFlow.EntityFramework.Tests.csproj", "{02B1E8B4-CC53-4BAB-BC2C-AD0B06760AE2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -145,6 +151,14 @@ Global
{8FAC191C-340D-47C6-B8AE-3D57783749C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8FAC191C-340D-47C6-B8AE-3D57783749C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8FAC191C-340D-47C6-B8AE-3D57783749C4}.Release|Any CPU.Build.0 = Release|Any CPU
{ED4AA905-A208-4E67-8B40-CC8E1B8440B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ED4AA905-A208-4E67-8B40-CC8E1B8440B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ED4AA905-A208-4E67-8B40-CC8E1B8440B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ED4AA905-A208-4E67-8B40-CC8E1B8440B8}.Release|Any CPU.Build.0 = Release|Any CPU
{02B1E8B4-CC53-4BAB-BC2C-AD0B06760AE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{02B1E8B4-CC53-4BAB-BC2C-AD0B06760AE2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{02B1E8B4-CC53-4BAB-BC2C-AD0B06760AE2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{02B1E8B4-CC53-4BAB-BC2C-AD0B06760AE2}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -175,6 +189,9 @@ Global
{74EFCDE2-CB0F-49B1-9CEC-BE748EB1FBF7} = {88359036-4F35-487C-BF2C-4F31C7BC92D8}
{D2B5B5CA-57C2-4354-ADB7-47A6D81AD521} = {74EFCDE2-CB0F-49B1-9CEC-BE748EB1FBF7}
{8FAC191C-340D-47C6-B8AE-3D57783749C4} = {74EFCDE2-CB0F-49B1-9CEC-BE748EB1FBF7}
{21A29AA0-EF82-4717-89CE-729257C05C7D} = {5EE323DE-E69B-451A-8AC3-22DD6A004FBA}
{ED4AA905-A208-4E67-8B40-CC8E1B8440B8} = {21A29AA0-EF82-4717-89CE-729257C05C7D}
{02B1E8B4-CC53-4BAB-BC2C-AD0B06760AE2} = {21A29AA0-EF82-4717-89CE-729257C05C7D}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {17607E2C-4E8E-45A2-85BD-0A5808E1C0F3}
Expand Down
Binary file added Source/.DS_Store
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -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<ThingyReadModelEntity, TestDbContext>()
.UseEntityFrameworkReadModel<ThingyMessageReadModelEntity, TestDbContext, ThingyMessageLocator>()
.AddQueryHandlers(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<IsPackable>False</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="3.1.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.1.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.11" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.11" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.11" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
<PackageReference Include="Npgsql" Version="4.1.14" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="3.1.4" />
<PackageReference Include="NUnit" Version="3.12.0" />
<PackageReference Include="Npgsql" Version="8.0.6" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.11" />
<PackageReference Include="NUnit" Version="3.13.2" />
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,26 +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 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
{
[Category(Categories.Integration)]
public class EfInMemoryEventStoreTests : TestSuiteForEventStore
{
protected override IRootResolver CreateRootResolver(IEventFlowOptions eventFlowOptions)
protected override IServiceProvider Configure(IEventFlowOptions eventFlowOptions)
{
return eventFlowOptions
eventFlowOptions
.ConfigureEntityFramework(EntityFrameworkConfiguration.New)
.AddDbContextProvider<TestDbContext, InMemoryDbContextProvider>(Lifetime.Singleton)
.ConfigureForEventStoreTest()
.CreateResolver();
.AddDbContextProvider<TestDbContext, InMemoryDbContextProvider>(ServiceLifetime.Singleton)
.ConfigureForEventStoreTest();

var serviceProvider = base.Configure(eventFlowOptions);

return serviceProvider;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
using EventFlow.EntityFramework.Tests.Model;
using EventFlow.TestHelpers;
using EventFlow.TestHelpers.Suites;
using Microsoft.Extensions.DependencyInjection;
using NUnit.Framework;

namespace EventFlow.EntityFramework.Tests.InMemory
Expand All @@ -35,13 +36,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
eventFlowOptions
.ConfigureEntityFramework(EntityFrameworkConfiguration.New)
.AddDbContextProvider<TestDbContext, InMemoryDbContextProvider>(Lifetime.Singleton)
.ConfigureForReadStoreTest()
.CreateResolver();
.AddDbContextProvider<TestDbContext, InMemoryDbContextProvider>(ServiceLifetime.Singleton)
.ConfigureForReadStoreTest();

var serviceProvider = base.Configure(eventFlowOptions);

return serviceProvider;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,30 @@
// 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.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
{
[Category(Categories.Integration)]
public class EfInMemorySnapshotTests : TestSuiteForSnapshotStore
{
protected override IRootResolver CreateRootResolver(IEventFlowOptions eventFlowOptions)
protected override IServiceProvider Configure(IEventFlowOptions eventFlowOptions)
{
return eventFlowOptions
eventFlowOptions
.ConfigureEntityFramework(EntityFrameworkConfiguration.New)
.AddDbContextProvider<TestDbContext, InMemoryDbContextProvider>(Lifetime.Singleton)
.ConfigureForSnapshotStoreTest()
.CreateResolver();
.AddDbContextProvider<TestDbContext, InMemoryDbContextProvider>(ServiceLifetime.Singleton)
.ConfigureForSnapshotStoreTest();

var serviceProvider = base.Configure(eventFlowOptions);

return serviceProvider;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,24 @@
// 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.Diagnostics.CodeAnalysis;
using EventFlow.EntityFramework.Tests.InMemory.Infrastructure;
using EventFlow.EntityFramework.Tests.Model;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.InMemory.Storage.Internal;

namespace EventFlow.EntityFramework.Tests.InMemory
{
[SuppressMessage("Usage", "EF1001:Internal EF Core API usage.", Justification = "Only for tests")]
public class InMemoryDbContextProvider : IDbContextProvider<TestDbContext>
{
private readonly DbContextOptions<TestDbContext> _options;

public InMemoryDbContextProvider()
{
_options = new DbContextOptionsBuilder<TestDbContext>()
.UseInMemoryDatabase("EventFlowTest")
.UseInMemoryDatabase($"EventFlowTest-{Guid.NewGuid()}")
.ReplaceService<IInMemoryTableFactory, IndexingInMemoryTableFactory>()
.Options;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -39,6 +40,12 @@ public class IndexingInMemoryTable : IInMemoryTable
private readonly HashSet<IndexEntry>[] _indexes;
private readonly IInMemoryTable _innerTable;

public IEnumerable<object[]> 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;
Expand All @@ -51,34 +58,39 @@ public IReadOnlyList<object[]> SnapshotRows()
return _innerTable.SnapshotRows();
}

public void Create(IUpdateEntry entry)
{
public void Create(IUpdateEntry entry, IDiagnosticsLogger<DbLoggerCategory.Update> updateLogger)
{
var indexEntries = _indexDefinitions
.Select(d => d.Properties.Select(entry.GetCurrentValue).ToArray())
.Select(values => new IndexEntry(values))
.ToArray();

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, updateLogger);

_ = indexEntries.Select((item, i) => _indexes[i].Add(item)).ToArray();
}

_innerTable.Create(entry);

indexEntries.Select((item, i) => _indexes[i].Add(item)).ToArray();
public void Delete(IUpdateEntry entry, IDiagnosticsLogger<DbLoggerCategory.Update> updateLogger)
{
_innerTable.Delete(entry, updateLogger);
}

public void Delete(IUpdateEntry entry)
public void Update(IUpdateEntry entry, IDiagnosticsLogger<DbLoggerCategory.Update> updateLogger)
{
_innerTable.Delete(entry);
_innerTable.Update(entry, updateLogger);
}

public void Update(IUpdateEntry entry)
public InMemoryIntegerValueGenerator<TProperty> GetIntegerValueGenerator<TProperty>(IProperty property, IReadOnlyList<IInMemoryTable> tables)
{
_innerTable.Update(entry);
return _innerTable.GetIntegerValueGenerator<TProperty>(property, tables);
}

public InMemoryIntegerValueGenerator<TProperty> GetIntegerValueGenerator<TProperty>(IProperty property)
public void BumpValueGenerators(object[] row)
{
return _innerTable.GetIntegerValueGenerator<TProperty>(property);
_innerTable.BumpValueGenerators(row);
}

private struct IndexEntry
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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 option) : base(loggingOptions, option)
{
}

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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
modelBuilder.Entity<PersonReadModelEntity>()
.Property(e => e.AggregateId)
.ValueGeneratedOnAdd();

modelBuilder.Entity<AddressReadModelEntity>()
.Property(e => e.AddressId)
.ValueGeneratedNever();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -41,19 +43,21 @@ public class ThingyMessageReadModelEntity : IReadModel,

public string Message { get; set; }

public void Apply(IReadModelContext context, IDomainEvent<ThingyAggregate, ThingyId, ThingyMessageAddedEvent> domainEvent)
public Task ApplyAsync(IReadModelContext context, IDomainEvent<ThingyAggregate, ThingyId, ThingyMessageAddedEvent> domainEvent, CancellationToken cancellationToken)
{
ThingyId = domainEvent.AggregateIdentity.Value;
Message = domainEvent.AggregateEvent.ThingyMessage.Message;
return Task.CompletedTask;
}

public void Apply(IReadModelContext context, IDomainEvent<ThingyAggregate, ThingyId, ThingyMessageHistoryAddedEvent> domainEvent)
public Task ApplyAsync(IReadModelContext context, IDomainEvent<ThingyAggregate, ThingyId, ThingyMessageHistoryAddedEvent> 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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -42,22 +44,25 @@ public class ThingyReadModelEntity : IReadModel,
[ConcurrencyCheck]
public long Version { get; set; }

public void Apply(IReadModelContext context,
IDomainEvent<ThingyAggregate, ThingyId, ThingyDeletedEvent> domainEvent)
public Task ApplyAsync(IReadModelContext context,
IDomainEvent<ThingyAggregate, ThingyId, ThingyDeletedEvent> domainEvent, CancellationToken cancellationToken)
{
context.MarkForDeletion();
return Task.CompletedTask;
}

public void Apply(IReadModelContext context,
IDomainEvent<ThingyAggregate, ThingyId, ThingyDomainErrorAfterFirstEvent> domainEvent)
public Task ApplyAsync(IReadModelContext context,
IDomainEvent<ThingyAggregate, ThingyId, ThingyDomainErrorAfterFirstEvent> domainEvent, CancellationToken cancellationToken)
{
DomainErrorAfterFirstReceived = true;
return Task.CompletedTask;
}

public void Apply(IReadModelContext context,
IDomainEvent<ThingyAggregate, ThingyId, ThingyPingEvent> domainEvent)
public Task ApplyAsync(IReadModelContext context,
IDomainEvent<ThingyAggregate, ThingyId, ThingyPingEvent> domainEvent, CancellationToken cancellationToken)
{
PingsReceived++;
return Task.CompletedTask;
}

public Thingy ToThingy()
Expand Down
Loading
Loading