Code re-factorings and formatting in IntegrationEventLogEF project

This commit is contained in:
Rafsanul Hasan 2018-09-09 05:18:08 +06:00
parent 0705dc0ab5
commit 1d377f7808
No known key found for this signature in database
GPG Key ID: FC57FD2D87BE60DD
6 changed files with 138 additions and 147 deletions

View File

@ -1,13 +1,9 @@
using System; namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF
using System.Collections.Generic;
using System.Text;
namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF
{ {
public enum EventStateEnum public enum EventStateEnum
{ {
NotPublished = 0, NotPublished = 0,
Published = 1, Published = 1,
PublishedFailed = 2 PublishedFailed = 2
} }
} }

View File

@ -1,48 +1,45 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Metadata.Builders;
using System;
using System.Collections.Generic;
using System.Text;
namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF
{ {
public class IntegrationEventLogContext : DbContext public class IntegrationEventLogContext : DbContext
{ {
public IntegrationEventLogContext(DbContextOptions<IntegrationEventLogContext> options) : base(options) public IntegrationEventLogContext(DbContextOptions<IntegrationEventLogContext> options) : base(options)
{ {
} }
public DbSet<IntegrationEventLogEntry> IntegrationEventLogs { get; set; } public DbSet<IntegrationEventLogEntry> IntegrationEventLogs { get; set; }
protected override void OnModelCreating(ModelBuilder builder) protected override void OnModelCreating(ModelBuilder builder)
{ {
builder.Entity<IntegrationEventLogEntry>(ConfigureIntegrationEventLogEntry); builder.Entity<IntegrationEventLogEntry>(ConfigureIntegrationEventLogEntry);
} }
void ConfigureIntegrationEventLogEntry(EntityTypeBuilder<IntegrationEventLogEntry> builder) void ConfigureIntegrationEventLogEntry(EntityTypeBuilder<IntegrationEventLogEntry> builder)
{ {
builder.ToTable("IntegrationEventLog"); builder.ToTable("IntegrationEventLog");
builder.HasKey(e => e.EventId); builder.HasKey(e => e.EventId);
builder.Property(e => e.EventId) builder.Property(e => e.EventId)
.IsRequired(); .IsRequired();
builder.Property(e => e.Content) builder.Property(e => e.Content)
.IsRequired(); .IsRequired();
builder.Property(e => e.CreationTime) builder.Property(e => e.CreationTime)
.IsRequired(); .IsRequired();
builder.Property(e => e.State) builder.Property(e => e.State)
.IsRequired(); .IsRequired();
builder.Property(e => e.TimesSent) builder.Property(e => e.TimesSent)
.IsRequired(); .IsRequired();
builder.Property(e => e.EventTypeName) builder.Property(e => e.EventTypeName)
.IsRequired(); .IsRequired();
} }
} }
} }

View File

@ -1,28 +1,28 @@
using System; using DateTime = System.DateTime;
using System.Collections.Generic; using Guid = System.Guid;
using System.Text; using JsonConvert = Newtonsoft.Json.JsonConvert;
using Newtonsoft.Json;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF
{ {
public class IntegrationEventLogEntry using IntegrationEvent = EventBus.Events.IntegrationEvent;
{
private IntegrationEventLogEntry() { } public class IntegrationEventLogEntry
public IntegrationEventLogEntry(IntegrationEvent @event) {
{ private IntegrationEventLogEntry() { }
EventId = @event.Id; public IntegrationEventLogEntry(IntegrationEvent @event)
CreationTime = @event.CreationDate; {
EventTypeName = @event.GetType().FullName; EventId = @event.Id;
Content = JsonConvert.SerializeObject(@event); CreationTime = @event.CreationDate;
State = EventStateEnum.NotPublished; EventTypeName = @event.GetType().FullName;
TimesSent = 0; Content = JsonConvert.SerializeObject(@event);
} State = EventStateEnum.NotPublished;
public Guid EventId { get; private set; } TimesSent = 0;
public string EventTypeName { get; private set; } }
public EventStateEnum State { get; set; } public Guid EventId { get; private set; }
public int TimesSent { get; set; } public string EventTypeName { get; private set; }
public DateTime CreationTime { get; private set; } public EventStateEnum State { get; set; }
public string Content { get; private set; } public int TimesSent { get; set; }
} public DateTime CreationTime { get; private set; }
public string Content { get; private set; }
}
} }

View File

@ -1,15 +1,13 @@
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; using DbTransaction = System.Data.Common.DbTransaction;
using System; using Task = System.Threading.Tasks.Task;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services
{ {
public interface IIntegrationEventLogService using IntegrationEvent = EventBus.Events.IntegrationEvent;
{
Task SaveEventAsync(IntegrationEvent @event, DbTransaction transaction); public interface IIntegrationEventLogService
Task MarkEventAsPublishedAsync(IntegrationEvent @event); {
} Task SaveEventAsync(IntegrationEvent @event, DbTransaction transaction);
Task MarkEventAsPublishedAsync(IntegrationEvent @event);
}
} }

View File

@ -1,52 +1,54 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics; using static System.Linq.Enumerable;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; using ArgumentNullException = System.ArgumentNullException;
using System; using DbConnection = System.Data.Common.DbConnection;
using System.Data.Common; using DbTransaction = System.Data.Common.DbTransaction;
using System.Linq; using RelationalEventId = Microsoft.EntityFrameworkCore.Diagnostics.RelationalEventId;
using System.Threading.Tasks; using Task = System.Threading.Tasks.Task;
namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services
{ {
public class IntegrationEventLogService : IIntegrationEventLogService using IntegrationEvent = EventBus.Events.IntegrationEvent;
{
private readonly IntegrationEventLogContext _integrationEventLogContext;
private readonly DbConnection _dbConnection;
public IntegrationEventLogService(DbConnection dbConnection) public class IntegrationEventLogService : IIntegrationEventLogService
{ {
_dbConnection = dbConnection ?? throw new ArgumentNullException(nameof(dbConnection)); private readonly IntegrationEventLogContext _integrationEventLogContext;
_integrationEventLogContext = new IntegrationEventLogContext( private readonly DbConnection _dbConnection;
new DbContextOptionsBuilder<IntegrationEventLogContext>()
.UseSqlServer(_dbConnection)
.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning))
.Options);
}
public Task SaveEventAsync(IntegrationEvent @event, DbTransaction transaction) public IntegrationEventLogService(DbConnection dbConnection)
{ {
if (transaction == null) _dbConnection = dbConnection ?? throw new ArgumentNullException(nameof(dbConnection));
{ _integrationEventLogContext = new IntegrationEventLogContext(
throw new ArgumentNullException(nameof(transaction), $"A {typeof(DbTransaction).FullName} is required as a pre-requisite to save the event."); new DbContextOptionsBuilder<IntegrationEventLogContext>()
} .UseSqlServer(_dbConnection)
.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning))
.Options);
}
var eventLogEntry = new IntegrationEventLogEntry(@event); public Task SaveEventAsync(IntegrationEvent @event, DbTransaction transaction)
{
if (transaction == null)
{
throw new ArgumentNullException(nameof(transaction), $"A {typeof(DbTransaction).FullName} is required as a pre-requisite to save the event.");
}
_integrationEventLogContext.Database.UseTransaction(transaction); var eventLogEntry = new IntegrationEventLogEntry(@event);
_integrationEventLogContext.IntegrationEventLogs.Add(eventLogEntry);
return _integrationEventLogContext.SaveChangesAsync(); _integrationEventLogContext.Database.UseTransaction(transaction);
} _integrationEventLogContext.IntegrationEventLogs.Add(eventLogEntry);
public Task MarkEventAsPublishedAsync(IntegrationEvent @event) return _integrationEventLogContext.SaveChangesAsync();
{ }
var eventLogEntry = _integrationEventLogContext.IntegrationEventLogs.Single(ie => ie.EventId == @event.Id);
eventLogEntry.TimesSent++;
eventLogEntry.State = EventStateEnum.Published;
_integrationEventLogContext.IntegrationEventLogs.Update(eventLogEntry); public Task MarkEventAsPublishedAsync(IntegrationEvent @event)
{
var eventLogEntry = _integrationEventLogContext.IntegrationEventLogs.Single(ie => ie.EventId == @event.Id);
eventLogEntry.TimesSent++;
eventLogEntry.State = EventStateEnum.Published;
return _integrationEventLogContext.SaveChangesAsync(); _integrationEventLogContext.IntegrationEventLogs.Update(eventLogEntry);
}
} return _integrationEventLogContext.SaveChangesAsync();
}
}
} }

View File

@ -1,37 +1,35 @@
using Microsoft.EntityFrameworkCore; using static Microsoft.EntityFrameworkCore.ExecutionStrategyExtensions;
using Microsoft.EntityFrameworkCore.Storage; using ArgumentNullException = System.ArgumentNullException;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; using DbContext = Microsoft.EntityFrameworkCore.DbContext;
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services; using Task = System.Threading.Tasks.Task;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Text;
using System.Threading.Tasks;
namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Utilities namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Utilities
{ {
public class ResilientTransaction using FuncOfTask = System.Func<Task>;
{
private DbContext _context;
private ResilientTransaction(DbContext context) =>
_context = context ?? throw new ArgumentNullException(nameof(context));
public static ResilientTransaction New (DbContext context) => public class ResilientTransaction
new ResilientTransaction(context); {
private DbContext _context;
private ResilientTransaction(DbContext context) =>
_context = context ?? throw new ArgumentNullException(nameof(context));
public async Task ExecuteAsync(Func<Task> action) public static ResilientTransaction New(DbContext context) =>
{ new ResilientTransaction(context);
//Use of an EF Core resiliency strategy when using multiple DbContexts within an explicit BeginTransaction():
//See: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency public async Task ExecuteAsync(FuncOfTask action)
var strategy = _context.Database.CreateExecutionStrategy(); {
await strategy.ExecuteAsync(async () => //Use of an EF Core resiliency strategy when using multiple DbContexts within an explicit BeginTransaction():
{ //See: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency
using (var transaction = _context.Database.BeginTransaction()) var strategy = _context.Database.CreateExecutionStrategy();
{ await strategy.ExecuteAsync(async () =>
await action(); {
transaction.Commit(); using (var transaction = _context.Database.BeginTransaction())
} {
}); await action();
} transaction.Commit();
} }
});
}
}
} }