Code re-factorings and formatting in IntegrationEventLogEF project
This commit is contained in:
parent
0705dc0ab5
commit
1d377f7808
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user