Skip to content

Commit

Permalink
Merge pull request #93 from marcwittke/develop
Browse files Browse the repository at this point in the history
6.1.1
  • Loading branch information
marcwittke committed Dec 24, 2019
2 parents fb5bc06 + 362317f commit 6c094e9
Show file tree
Hide file tree
Showing 19 changed files with 58 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
namespace Backend.Fx.Patterns.UnitOfWork
{
/// <summary>
/// Enriches the unit of work to use a database transaction during lifetime.
/// Enriches the unit of work to use a database transaction during lifetime. The transaction gets started, before IUnitOfWork.Begin()
/// is being called and gets committed after IUnitOfWork.Complete() is being called.
/// </summary>
public class DbTransactionDecorator : IUnitOfWork
{
Expand All @@ -21,13 +22,13 @@ public DbTransactionDecorator(ITransactionContext transactionContext, IUnitOfWor

public ICurrentTHolder<IIdentity> IdentityHolder => UnitOfWork.IdentityHolder;

public void Begin()
public virtual void Begin()
{
TransactionContext.BeginTransaction();
UnitOfWork.Begin();
}

public void Complete()
public virtual void Complete()
{
UnitOfWork.Complete();
TransactionContext.CommitTransaction();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc.Filters;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Mvc.Filters;

namespace Backend.Fx.AspNetCore.Mvc.Throttling
{
Expand All @@ -10,17 +11,20 @@ public abstract class ThrottlingBaseAttribute : ActionFilterAttribute
/// <remarks>
/// We'll be inserting a Cache record based on this name and client IP, e.g. "Name-192.168.0.1"
/// </remarks>
[UsedImplicitly]
public string Name { get; set; }

/// <summary>
/// The number of seconds clients must wait before executing this decorated route again.
/// </summary>
[UsedImplicitly]
public int Seconds { get; set; }

/// <summary>
/// A text message that will be sent to the client upon throttling. You can include the token {0} to
/// A text message that will be sent to the client upon throttling. You can include the token {0} to
/// show this.Seconds in the message, e.g. "Wait {0} seconds before trying again".
/// </summary>
[UsedImplicitly]
public string Message { get; set; } = "Wait {0} seconds before trying again";

protected virtual int CalculateRepeatedTimeoutFactor(int repetition)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Threading.Tasks;
using Backend.Fx.Logging;
using Backend.Fx.Patterns.DependencyInjection;
using Backend.Fx.Patterns.UnitOfWork;
using JetBrains.Annotations;
Expand All @@ -13,7 +12,6 @@ namespace Backend.Fx.AspNetCore.UnitOfWork
/// </summary>
public class UnitOfWorkMiddleware
{
private static readonly ILogger Logger = LogManager.Create<UnitOfWorkMiddleware>();
private readonly RequestDelegate _next;
private readonly IBackendFxApplication _application;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,16 @@ public static void ApplyAggregateMappings(this DbContext dbContext, ModelBuilder
.ExportedTypes
.Select(t => t.GetTypeInfo())
.Where(t => t.IsClass && !t.IsAbstract && !t.IsGenericType && typeof(IAggregateMapping).GetTypeInfo().IsAssignableFrom(t));
foreach (var typeInfo in aggregateDefinitionTypeInfos)
foreach (TypeInfo typeInfo in aggregateDefinitionTypeInfos)
{
IAggregateMapping aggregateMapping = (IAggregateMapping)Activator.CreateInstance(typeInfo.AsType());
var aggregateMapping = (IAggregateMapping)Activator.CreateInstance(typeInfo.AsType());
aggregateMapping.ApplyEfMapping(modelBuilder);
}
}

public static void UpdateTrackingProperties(this DbContext dbContext, string userId, DateTime utcNow)
{
userId = userId ?? "anonymous";
userId ??= "anonymous";
var isTraceEnabled = Logger.IsTraceEnabled();
int count = 0;

Expand All @@ -61,7 +61,6 @@ public static void UpdateTrackingProperties(this DbContext dbContext, string use
.Where(entry => entry.State == EntityState.Added || entry.State == EntityState.Modified || entry.State == EntityState.Deleted)
.Where(entry => !(entry.Entity is AggregateRoot))
.ToArray()
.AsParallel()
.ForAll(entry =>
{
EntityEntry aggregateRootEntry = FindAggregateRootEntry(dbContext.ChangeTracker, entry);
Expand Down Expand Up @@ -116,9 +115,10 @@ public static void UpdateTrackingProperties(this DbContext dbContext, string use
/// </summary>
private static EntityEntry FindAggregateRootEntry(ChangeTracker changeTracker, EntityEntry entry)
{
foreach (var navigation in entry.Navigations)
Logger.Debug($"Searching aggregate root of {entry.Entity.GetType().Name}[{(entry.Entity as Identified)?.Id}]");
foreach (NavigationEntry navigation in entry.Navigations)
{
var navTargetTypeInfo = navigation.Metadata.GetTargetType().ClrType.GetTypeInfo();
TypeInfo navTargetTypeInfo = navigation.Metadata.GetTargetType().ClrType.GetTypeInfo();
int navigationTargetForeignKeyValue;

if (navigation.CurrentValue == null)
Expand Down Expand Up @@ -152,6 +152,7 @@ private static EntityEntry FindAggregateRootEntry(ChangeTracker changeTracker, E
}

// recurse in case of "Entity -> Entity -> AggregateRoot"
Logger.Debug("Recursing...");
return FindAggregateRootEntry(changeTracker, navigationTargetEntry);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,52 +1,32 @@
using System;
using System.Data.Common;
using System.Security.Principal;
using Backend.Fx.Patterns.DependencyInjection;
using Backend.Fx.Patterns.Transactions;
using Backend.Fx.Patterns.UnitOfWork;
using Microsoft.EntityFrameworkCore;

namespace Backend.Fx.EfCorePersistence
{
/// <summary>
/// Makes sure the DbContext gets enlisted in a transaction. The transaction gets started, before IUnitOfWork.Begin() is being called
/// and gets committed after IUnitOfWork.Complete() is being called
/// Makes sure the DbContext gets enlisted in a transaction.
/// </summary>
public class DbContextTransactionDecorator : IUnitOfWork
public class DbContextTransactionDecorator : DbTransactionDecorator
{
public DbContextTransactionDecorator(ITransactionContext transactionContext, DbContext dbContext, IUnitOfWork unitOfWork)
: base(transactionContext, unitOfWork)
{
TransactionContext = transactionContext;
DbContext = dbContext;
UnitOfWork = unitOfWork;
}

public IUnitOfWork UnitOfWork { get; }

public ITransactionContext TransactionContext { get; }

public DbContext DbContext { get; }

public ICurrentTHolder<IIdentity> IdentityHolder => UnitOfWork.IdentityHolder;

public void Begin()
public override void Begin()
{
TransactionContext.BeginTransaction();
base.Begin();
if (DbContext.Database.GetDbConnection() != TransactionContext.CurrentTransaction.Connection)
{
throw new InvalidOperationException("The connection used by the DbContext instance does not equal the connection of the transaction context");
}
DbContext.Database.UseTransaction((DbTransaction) TransactionContext.CurrentTransaction);
UnitOfWork.Begin();
}

public void Complete()
{
UnitOfWork.Complete();
TransactionContext.CommitTransaction();
}

public void Dispose()
{ }
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Security;
using Backend.Fx.BuildingBlocks;
Expand Down Expand Up @@ -59,9 +60,9 @@ protected set
/// </summary>
/// <param name="entry"></param>
/// <param name="previousState"></param>
[SuppressMessage("ReSharper", "EF1001")]
private void AuthorizeChanges(InternalEntityEntry entry, EntityState previousState)
{
// ReSharper disable EF1001
if (previousState == EntityState.Unchanged && entry.EntityState == EntityState.Modified && entry.EntityType.ClrType == typeof(TAggregateRoot))
{
var aggregateRoot = (TAggregateRoot) entry.Entity;
Expand All @@ -70,7 +71,6 @@ private void AuthorizeChanges(InternalEntityEntry entry, EntityState previousSta
throw new SecurityException($"You are not allowed to modify {AggregateTypeName}[{aggregateRoot.Id}]");
}
}
// ReSharper restore EF1001
}

protected override void AddPersistent(TAggregateRoot aggregateRoot)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ namespace Backend.Fx.InMemoryPersistence
public class InMemoryUnitOfWork : UnitOfWork
{
public int CommitCalls { get; private set; }
public int RollbackCalls { get; private set; }


public InMemoryUnitOfWork(IClock clock, ICurrentTHolder<IIdentity> identityHolder,
IDomainEventAggregator eventAggregator, IEventBusScope eventBusScope)
: base(clock, identityHolder, eventAggregator, eventBusScope)
Expand Down
8 changes: 4 additions & 4 deletions src/implementations/Backend.Fx.NLogLogging/Configurations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ public static void ForTests(string appRootNamespace, string logfilename = "tests
{
lock (SyncLock)
{
if (NLog.LogManager.Configuration != null) return;
if (LogManager.Configuration != null) return;

Backend.Fx.Logging.LogManager.Initialize(new NLogLoggerFactory());
Logging.LogManager.Initialize(new NLogLoggerFactory());
var config = new LoggingConfiguration();

var consoleTarget = new ConsoleTarget
Expand Down Expand Up @@ -66,7 +66,7 @@ public static void ForTests(string appRootNamespace, string logfilename = "tests
config.AddTarget(warnings);
config.LoggingRules.Add(new LoggingRule("*", LogLevel.Warn, LogLevel.Warn, warnings));

NLog.LogManager.Configuration = config;
LogManager.Configuration = config;

Console.WriteLine($"Test console shows only warn, error and fatal events. Full log file is available at {Path.Combine(AppContext.BaseDirectory, logfilename)}");
}
Expand All @@ -79,7 +79,7 @@ public static IEnumerable<string> LogMessages(LogLevel level)

public static IEnumerable<string> LogMessages(string level)
{
return NLog.LogManager.Configuration?.FindTargetByName<MemoryTarget>(level)?.Logs ?? Enumerable.Empty<string>();
return LogManager.Configuration?.FindTargetByName<MemoryTarget>(level)?.Logs ?? Enumerable.Empty<string>();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ protected LoggingFixture(string appRootNamespace)
{
Configurations.ForTests(appRootNamespace, GetType().GetTypeInfo().Assembly.GetName().Name + ".xlog");

_lifetimeLogger = Backend.Fx.Logging.LogManager.Create<LoggingFixture>().InfoDuration("Test run started", "Test run finished");
_lifetimeLogger = Logging.LogManager.Create<LoggingFixture>().InfoDuration("Test run started", "Test run finished");
}

public void Dispose()
Expand Down
14 changes: 7 additions & 7 deletions src/implementations/Backend.Fx.NLogLogging/NLogLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using System;
using System.Diagnostics;
using System.Globalization;
using BackendFxILogger = Backend.Fx.Logging.ILogger;
using BackendFxILogger = Logging.ILogger;

using NLogILogger = NLog.ILogger;
using NLogLogLevel = NLog.LogLevel;
Expand Down Expand Up @@ -84,12 +84,12 @@ public Exception Info(Exception exception)

public IDisposable InfoDuration(string activity)
{
return new Backend.Fx.Logging.DurationLogger(s => Info(s), activity);
return new Logging.DurationLogger(s => Info(s), activity);
}

public IDisposable InfoDuration(string beginMessage, string endMessage)
{
return new Backend.Fx.Logging.DurationLogger(s => Info(s), beginMessage, endMessage);
return new Logging.DurationLogger(s => Info(s), beginMessage, endMessage);
}

public void Info(string format, params object[] args)
Expand Down Expand Up @@ -118,12 +118,12 @@ public Exception Debug(Exception exception)

public IDisposable DebugDuration(string activity)
{
return new Backend.Fx.Logging.DurationLogger(s => Debug(s), activity);
return new Logging.DurationLogger(s => Debug(s), activity);
}

public IDisposable DebugDuration(string beginMessage, string endMessage)
{
return new Backend.Fx.Logging.DurationLogger(s => Debug(s), beginMessage, endMessage);
return new Logging.DurationLogger(s => Debug(s), beginMessage, endMessage);
}

public void Debug(string format, params object[] args)
Expand Down Expand Up @@ -153,12 +153,12 @@ public Exception Trace(Exception exception)

public IDisposable TraceDuration(string activity)
{
return new Backend.Fx.Logging.DurationLogger(s => Trace(s), activity);
return new Logging.DurationLogger(s => Trace(s), activity);
}

public IDisposable TraceDuration(string beginMessage, string endMessage)
{
return new Backend.Fx.Logging.DurationLogger(s => Trace(s), beginMessage, endMessage);
return new Logging.DurationLogger(s => Trace(s), beginMessage, endMessage);
}

public void Trace(string format, params object[] args)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
using System.Diagnostics;

[DebuggerStepThrough]
public class NLogLoggerFactory : Backend.Fx.Logging.ILoggerFactory
public class NLogLoggerFactory : Logging.ILoggerFactory
{
public NLogLoggerFactory()
{
BeginActivity(0);
}

public Backend.Fx.Logging.ILogger Create(string s)
public Logging.ILogger Create(string s)
{
return new NLogLogger(NLog.LogManager.GetLogger(s));
}
Expand All @@ -27,7 +27,7 @@ public void Shutdown()

public static void Configure(string nlogConfigPath)
{
Backend.Fx.Logging.LogManager.Initialize(new NLogLoggerFactory());
Logging.LogManager.Initialize(new NLogLoggerFactory());
NLog.LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(nlogConfigPath);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public SimpleInjectorCompositionRoot(ILifestyleSelectionBehavior lifestyleBehavi
Container.Options.DefaultScopedLifestyle = ScopedLifestyle;
}

internal Container Container { get; } = new Container();
public Container Container { get; } = new Container();

internal ScopedLifestyle ScopedLifestyle { get; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@ public Post(int id, Blog blog, string name, bool isPublic=false) : base(id)
TargetAudience = new TargetAudience {IsPublic = isPublic, Culture = "fr-FR"};
}

public int BlogId { get; [UsedImplicitly] private set; }
public Blog Blog { get; [UsedImplicitly] private set; }
[UsedImplicitly]
public int BlogId { get; private set; }
[UsedImplicitly]
public Blog Blog { get; private set; }
[UsedImplicitly]
public string Name { get; private set; }

[UsedImplicitly]
public TargetAudience TargetAudience { get; set; }

public void SetName(string name)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
modelBuilder.RegisterEntityIdAsNeverGenerated();
}

public DbSet<Blogger> Bloggers { get; set; }
public DbSet<Blogger> Bloggers { get; [UsedImplicitly] set; }

public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
public DbSet<Tenant> Tenants { get; set; }
public DbSet<Blog> Blogs { get; [UsedImplicitly] set; }
public DbSet<Post> Posts { get; [UsedImplicitly] set; }
public DbSet<Tenant> Tenants { get; [UsedImplicitly] set; }
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
// ReSharper disable RedundantArgumentDefaultValue

namespace Backend.Fx.EfCorePersistence.Tests.Migrations
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using Backend.Fx.EfCorePersistence.Tests.DummyImpl.Persistence;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;

namespace Backend.Fx.EfCorePersistence.Tests.Migrations
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ public AnIntegrationEvent(int tenantId, int whatever) : base(tenantId)
Whatever = whatever;
}

public int Whatever { get; }
public int Whatever { [UsedImplicitly] get; }
}
}

0 comments on commit 6c094e9

Please sign in to comment.