Browse Source

Code re-factorings and formatting in IntegrationEventLogEF project

pull/762/head
Rafsanul Hasan 6 years ago
parent
commit
1d377f7808
No known key found for this signature in database GPG Key ID: FC57FD2D87BE60DD
6 changed files with 146 additions and 155 deletions
  1. +7
    -11
      src/BuildingBlocks/EventBus/IntegrationEventLogEF/EventStateEnum.cs
  2. +28
    -31
      src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogContext.cs
  3. +24
    -24
      src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEntry.cs
  4. +9
    -11
      src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IIntegrationEventLogService.cs
  5. +49
    -47
      src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IntegrationEventLogService.cs
  6. +29
    -31
      src/BuildingBlocks/EventBus/IntegrationEventLogEF/Utilities/ResilientTransaction.cs

+ 7
- 11
src/BuildingBlocks/EventBus/IntegrationEventLogEF/EventStateEnum.cs View File

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

+ 28
- 31
src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogContext.cs 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 IntegrationEventLogContext(DbContextOptions<IntegrationEventLogContext> options) : base(options)
{
}
public class IntegrationEventLogContext : DbContext
{
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)
{
builder.Entity<IntegrationEventLogEntry>(ConfigureIntegrationEventLogEntry);
}
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<IntegrationEventLogEntry>(ConfigureIntegrationEventLogEntry);
}
void ConfigureIntegrationEventLogEntry(EntityTypeBuilder<IntegrationEventLogEntry> builder)
{
builder.ToTable("IntegrationEventLog");
void ConfigureIntegrationEventLogEntry(EntityTypeBuilder<IntegrationEventLogEntry> builder)
{
builder.ToTable("IntegrationEventLog");
builder.HasKey(e => e.EventId);
builder.HasKey(e => e.EventId);
builder.Property(e => e.EventId)
.IsRequired();
builder.Property(e => e.EventId)
.IsRequired();
builder.Property(e => e.Content)
.IsRequired();
builder.Property(e => e.Content)
.IsRequired();
builder.Property(e => e.CreationTime)
.IsRequired();
builder.Property(e => e.CreationTime)
.IsRequired();
builder.Property(e => e.State)
.IsRequired();
builder.Property(e => e.State)
.IsRequired();
builder.Property(e => e.TimesSent)
.IsRequired();
builder.Property(e => e.TimesSent)
.IsRequired();
builder.Property(e => e.EventTypeName)
.IsRequired();
builder.Property(e => e.EventTypeName)
.IsRequired();
}
}
}
}
} }

+ 24
- 24
src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEntry.cs View File

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

+ 9
- 11
src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IIntegrationEventLogService.cs View File

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

+ 49
- 47
src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IntegrationEventLogService.cs View File

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

+ 29
- 31
src/BuildingBlocks/EventBus/IntegrationEventLogEF/Utilities/ResilientTransaction.cs View File

@ -1,37 +1,35 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Text;
using System.Threading.Tasks;
using static Microsoft.EntityFrameworkCore.ExecutionStrategyExtensions;
using ArgumentNullException = System.ArgumentNullException;
using DbContext = Microsoft.EntityFrameworkCore.DbContext;
using Task = System.Threading.Tasks.Task;
namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Utilities namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Utilities
{ {
public class ResilientTransaction
{
private DbContext _context;
private ResilientTransaction(DbContext context) =>
_context = context ?? throw new ArgumentNullException(nameof(context));
using FuncOfTask = System.Func<Task>;
public class ResilientTransaction
{
private DbContext _context;
private ResilientTransaction(DbContext context) =>
_context = context ?? throw new ArgumentNullException(nameof(context));
public static ResilientTransaction New (DbContext context) =>
new ResilientTransaction(context);
public static ResilientTransaction New(DbContext context) =>
new ResilientTransaction(context);
public async Task ExecuteAsync(Func<Task> action)
{
//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
var strategy = _context.Database.CreateExecutionStrategy();
await strategy.ExecuteAsync(async () =>
{
using (var transaction = _context.Database.BeginTransaction())
{
await action();
transaction.Commit();
}
});
}
}
public async Task ExecuteAsync(FuncOfTask action)
{
//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
var strategy = _context.Database.CreateExecutionStrategy();
await strategy.ExecuteAsync(async () =>
{
using (var transaction = _context.Database.BeginTransaction())
{
await action();
transaction.Commit();
}
});
}
}
} }

Loading…
Cancel
Save