Skip to content

Commit

Permalink
Merge pull request #5 from wilcommerce/release/1.0.0
Browse files Browse the repository at this point in the history
Release 1.0.0
  • Loading branch information
albx authored Nov 9, 2019
2 parents 5ab0f82 + b1ff339 commit e93273d
Show file tree
Hide file tree
Showing 12 changed files with 243 additions and 74 deletions.
33 changes: 30 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,45 @@
# Wilcommerce.Core.Data.EFCore
Contains an implementation of the [Wilcommerce.Core](https://github.com/wilcommerce/Wilcommerce.Core) packages using Entity Framework Core as persistence framework.

## Requirements
According to Entity Framework Core 3.0 requirements, this project is built using NETStandard 2.1 as Target Framework (See [https://docs.microsoft.com/it-it/ef/core/what-is-new/ef-core-3.0/breaking-changes#netstandard21](https://docs.microsoft.com/it-it/ef/core/what-is-new/ef-core-3.0/breaking-changes#netstandard21) for further informations).

This means it will not run on projects which target .NET Framework.

If you have some specific needs you can [open a issue on GitHub](https://github.com/wilcommerce/Wilcommerce.Core.Data.EFCore/issues) or you can consider to [contribute to Wilcommerce](CONTRIBUTING.md).

## Installation

Nuget package available here

[https://www.nuget.org/packages/Wilcommerce.Core.Data.EFCore](https://www.nuget.org/packages/Wilcommerce.Core.Data.EFCore)

## Usage
Add the the EventsContext class to your project.
Add the the EventsContext class to your ASP.NET Core project.
```<C#>
services.AddDbContext<EventsContext>(options => // Specify your provider);
services.AddDbContext<EventsContext>(options =>
options.UseSqlServer("[ConnectionStringName]",
b => b.MigrationAssembly("[Your assembly name]")));
```
The EventsContext is injected in the EventStore implementation.

After the DbContext has been registered in the ServiceCollection, you need to add a migration using **donet** CLI or the **Package Manager Console**.
```
// Using dotnet CLI
dotnet ef migrations add -c Wilcommerce.Core.Data.EFCore.EventsContext Initial
// Using Package Manager Console
EntityFrameworkCore\Add-Migration -Context Wilcommerce.Core.Data.EFCore.EventsContext Initial
```

After this, you can update your database:
```
// Using dotnet CLI
dotnet ef database update -c Wilcommerce.Core.Data.EFCore.EventsContext
// Using Package Manager Console
EntityFrameworkCore\Update-Database -Context Wilcommerce.Core.Data.EFCore.EventsContext
```
The EventsContext is injected in the EventStore implementation

## EventStore Component
The EventStore class is the Entity Framework Core implementation of the [IEventStore](https://github.com/wilcommerce/Wilcommerce.Core/blob/master/src/Wilcommerce.Core.Infrastructure/IEventStore.cs) interface.
Expand Down
134 changes: 121 additions & 13 deletions Wilcommerce.Core.Data.EFCore.Test/Events/EventStoreTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Linq;
using Wilcommerce.Core.Data.EFCore.Events;
using Wilcommerce.Core.Data.EFCore.Test.Fixtures;
using Wilcommerce.Core.Infrastructure;
using Xunit;

namespace Wilcommerce.Core.Data.EFCore.Test.Events
Expand All @@ -10,37 +11,144 @@ public class EventStoreTest : IClassFixture<EventsFixtures>
{
private EventsFixtures _fixtures;

private EventStore _eventStore;

public EventStoreTest(EventsFixtures fixtures)
{
_fixtures = fixtures;
_eventStore = new EventStore(_fixtures.Context);
}

[Fact]
public void Ctor_Should_Throw_ArgumentNullException_If_EventsContext_Is_Null()
{
EventsContext context = null;

var ex = Assert.Throws<ArgumentNullException>(() => new EventStore(context));
Assert.Equal(nameof(context), ex.ParamName);
}

[Fact]
public void Find_NewAdministratorCreatedEvent_Should_Return_Rows_And_Match_Email_And_Name()
{
var events = _eventStore.Find<NewAdministratorCreatedEvent>(DateTime.Now);
int count = events.Count();
using (var context = _fixtures.BuildContext())
{
var eventStore = new EventStore(context);
_fixtures.PrepareData(context, new NewAdministratorCreatedEvent[]
{
new NewAdministratorCreatedEvent(_fixtures.UserId, "Administrator", "[email protected]")
});

var events = eventStore.Find<NewAdministratorCreatedEvent>(DateTime.Now);
int count = events.Count();

Assert.True(count > 0);

bool exists = events.Any(e => e.Email == "[email protected]" && e.Name == "Administrator");
Assert.True(exists);

_fixtures.CleanAllData(context);
}
}

[Fact]
public void FindAll_Should_Return_All_Events_Related_To_Specified_Entity()
{
using (var context = _fixtures.BuildContext())
{
var eventStore = new EventStore(context);
_fixtures.PrepareData(context, new DomainEvent[]
{
new NewAdministratorCreatedEvent(_fixtures.UserId, "Administrator", "[email protected]"),
new UserEnabledEvent(_fixtures.UserId),
new UserDisabledEvent(_fixtures.UserId)
});

var entityType = typeof(User);
var events = eventStore.FindAll(entityType.ToString(), _fixtures.UserId, DateTime.Now);

int count = events.Count();
Assert.True(count == 3);

_fixtures.CleanAllData(context);
}
}

[Fact]
public void Find_NewAdministratorCreatedEvent_By_EntityType_And_TimeStamp_Should_Return_Rows_And_Match_Email_And_Name()
{
using (var context = _fixtures.BuildContext())
{
var eventStore = new EventStore(context);
_fixtures.PrepareData(context, new NewAdministratorCreatedEvent[]
{
new NewAdministratorCreatedEvent(_fixtures.UserId, "Administrator", "[email protected]")
});

var entityType = typeof(User);
var events = eventStore.Find<NewAdministratorCreatedEvent>(entityType.ToString(), DateTime.Now);
int count = events.Count();

Assert.True(count > 0);

bool exists = events.Any(e => e.Email == "[email protected]" && e.Name == "Administrator" && e.AggregateType == entityType);
Assert.True(exists);

_fixtures.CleanAllData(context);
}
}

[Fact]
public void Find_NewAdministratorCreatedEvent_By_EntityType_EntityId_And_TimeStamp_Should_Return_Rows_And_Match_Email_And_Name()
{
using (var context = _fixtures.BuildContext())
{
var eventStore = new EventStore(context);
_fixtures.PrepareData(context, new NewAdministratorCreatedEvent[]
{
new NewAdministratorCreatedEvent(_fixtures.UserId, "Administrator", "[email protected]")
});

var entityType = typeof(User);
var events = eventStore.Find<NewAdministratorCreatedEvent>(entityType.ToString(), _fixtures.UserId, DateTime.Now);
int count = events.Count();

Assert.True(count > 0);

bool exists = events.Any(e => e.Email == "[email protected]" && e.Name == "Administrator" && e.AggregateId == _fixtures.UserId && e.AggregateType == entityType);
Assert.True(exists);

_fixtures.CleanAllData(context);
}
}

[Fact]
public void Save_Should_Throw_ArgumentNullException_If_Event_Is_Null()
{
using (var context = _fixtures.BuildContext())
{
var eventStore = new EventStore(context);

Assert.True(count > 0);
DomainEvent @event = null;
var ex = Assert.Throws<ArgumentNullException>(() => eventStore.Save(@event));

bool exists = events.Any(e => e.Email == "[email protected]" && e.Name == "Administrator");
Assert.True(exists);
Assert.Equal(nameof(@event), ex.ParamName);
}
}

[Fact]
public void Save_NewAdministratorCreatedEvent_Should_Increment_EventsNumber()
{
int count = _eventStore.Find<NewAdministratorCreatedEvent>(DateTime.Now).Count();
using (var context = _fixtures.BuildContext())
{
var eventStore = new EventStore(context);

var ev = new NewAdministratorCreatedEvent(Guid.NewGuid(), "Administrator2", "[email protected]");
eventStore.Save(ev);

var ev = new NewAdministratorCreatedEvent(Guid.NewGuid(), "Administrator2", "[email protected]");
_eventStore.Save(ev);
int count = eventStore.Find<NewAdministratorCreatedEvent>(DateTime.Now).Count();

int newCount = _eventStore.Find<NewAdministratorCreatedEvent>(DateTime.Now).Count();
Assert.Equal(1, count);

Assert.Equal(count + 1, newCount);
_fixtures.CleanAllData(context);
}
}
}
}
53 changes: 22 additions & 31 deletions Wilcommerce.Core.Data.EFCore.Test/Fixtures/EventsFixtures.cs
Original file line number Diff line number Diff line change
@@ -1,67 +1,58 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using Wilcommerce.Core.Common.Events;
using Wilcommerce.Core.Infrastructure;

namespace Wilcommerce.Core.Data.EFCore.Test.Fixtures
{
public class EventsFixtures : IDisposable
{
public EventsContext Context { get; protected set; }

public Guid UserId { get; protected set; }

private DbContextOptions<EventsContext> _contextOptions;

public EventsFixtures()
{
UserId = Guid.NewGuid();

BuildContext();
PrepareData();
BuildContextOptions();
}

public void Dispose()
public EventsContext BuildContext()
{
CleanData();

if (Context != null)
{
Context.Dispose();
}

GC.SuppressFinalize(this);
return new EventsContext(this._contextOptions);
}

protected virtual void PrepareData()
public void PrepareData(EventsContext context, IEnumerable<DomainEvent> events)
{
var administratorCreatedEvent = new NewAdministratorCreatedEvent(UserId, "Administrator", "[email protected]");
Context.Events.Add(EventWrapper.Wrap(administratorCreatedEvent));

for (int i = 0; i < 3; i++)
if (events != null && events.Count() > 0)
{
var ev = new UserEnabledEvent(UserId);
Context.Events.Add(EventWrapper.Wrap(ev));
}
var eventsWrapped = events.Select(ev => EventWrapper.Wrap(ev)).ToArray();
context.AddRange(eventsWrapped);

for (int i = 0; i < 2; i++)
{
var ev = new UserDisabledEvent(UserId);
Context.Events.Add(EventWrapper.Wrap(ev));
context.SaveChanges();
}
}

Context.SaveChanges();
public void CleanAllData(EventsContext context)
{
context.RemoveRange(context.Events);
context.SaveChanges();
}

protected virtual void CleanData()
public void Dispose()
{
Context.Events.RemoveRange(Context.Events);
GC.SuppressFinalize(this);
}

protected virtual void BuildContext()
protected virtual void BuildContextOptions()
{
var options = new DbContextOptionsBuilder<EventsContext>()
.UseInMemoryDatabase(databaseName: "InMemory-Events")
.Options;

Context = new EventsContext(options);
this._contextOptions = options;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public class NewAdministratorCreatedEvent : DomainEvent
public string Email { get; private set; }

public NewAdministratorCreatedEvent(Guid userId, string name, string email)
: base(userId ,typeof(NewAdministratorCreatedEvent))
: base(userId ,typeof(User))
{
UserId = userId;
Name = name;
Expand Down
13 changes: 13 additions & 0 deletions Wilcommerce.Core.Data.EFCore.Test/Fixtures/User.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System;

namespace Wilcommerce.Core.Data.EFCore.Test.Fixtures
{
public class User
{
public Guid Id { get; set; }

public string Name { get; set; }

public string Email { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public class UserDisabledEvent : DomainEvent
public Guid UserId { get; private set; }

public UserDisabledEvent(Guid userId)
: base(userId, typeof(UserDisabledEvent))
: base(userId, typeof(User))
{
UserId = userId;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public class UserEnabledEvent : DomainEvent
public Guid UserId { get; private set; }

public UserEnabledEvent(Guid userId)
: base(userId, typeof(UserEnabledEvent))
: base(userId, typeof(User))
{
UserId = userId;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<TargetFramework>netcoreapp3.0</TargetFramework>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="2.1.3" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.8.0" />
<PackageReference Include="Moq" Version="4.10.0" />
<PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0">
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="3.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" />
<PackageReference Include="Moq" Version="4.13.1" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
Expand Down
Binary file added icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit e93273d

Please sign in to comment.