diff --git a/src/MongoDM/MongoDM.csproj b/src/MongoDM/MongoDM.csproj index 330a1b8f..0a4a5fc4 100644 --- a/src/MongoDM/MongoDM.csproj +++ b/src/MongoDM/MongoDM.csproj @@ -1,23 +1,23 @@  - netcoreapp2.2 + netstandard2.0 true Digicando.MongoDM true - 0.18.2 + 0.18.3 Digicando Srl ODM framework for MongoDB - - + + - - - + + + diff --git a/src/MongoDM/Serialization/DocumentSchemaMemberMap.cs b/src/MongoDM/Serialization/DocumentSchemaMemberMap.cs index 41af879a..a79c176c 100644 --- a/src/MongoDM/Serialization/DocumentSchemaMemberMap.cs +++ b/src/MongoDM/Serialization/DocumentSchemaMemberMap.cs @@ -60,7 +60,7 @@ public IEnumerable MemberPathToId // Methods. public string MemberPathToString() => - string.Join('.', MemberPath.Select(member => member.MemberMap.MemberInfo.Name)); + string.Join(".", MemberPath.Select(member => member.MemberMap.MemberInfo.Name)); public string FullPathToString() => $"{RootModelType.Name}.{MemberPathToString()}"; diff --git a/src/MongoDM/ServiceCollectionExtensions.cs b/src/MongoDM/ServiceCollectionExtensions.cs index 266bd658..4945335d 100644 --- a/src/MongoDM/ServiceCollectionExtensions.cs +++ b/src/MongoDM/ServiceCollectionExtensions.cs @@ -23,6 +23,8 @@ public static void AddMongoDM(this I services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); // Proxy generator. diff --git a/src/MongoDM/Utility/ContextAccessorFacade.cs b/src/MongoDM/Utility/ContextAccessorFacade.cs index f9329bbe..d13aa6e4 100644 --- a/src/MongoDM/Utility/ContextAccessorFacade.cs +++ b/src/MongoDM/Utility/ContextAccessorFacade.cs @@ -9,14 +9,17 @@ class ContextAccessorFacade : IContextAccessorFacade { // Fields. private readonly IHttpContextAccessor httpContextAccessor; + private readonly ILocalContextAccessor localContextAccessor; private readonly IHangfireContextAccessor performContextAccessor; // Constructors. public ContextAccessorFacade( IHttpContextAccessor httpContextAccessor, + ILocalContextAccessor localContextAccessor, IHangfireContextAccessor performContextAccessor) { this.httpContextAccessor = httpContextAccessor; // Provided by Asp.Net, available only on client call. + this.localContextAccessor = localContextAccessor; // Optional context created by user on local async method stack. this.performContextAccessor = performContextAccessor; // Provided by HangFire, available only during task execution. } @@ -25,12 +28,13 @@ public IReadOnlyDictionary Items { get { + if (localContextAccessor.Context != null) + return localContextAccessor.Context.Items.ToDictionary(pair => pair.Key as object, pair => pair.Value); if (httpContextAccessor.HttpContext != null) return httpContextAccessor.HttpContext.Items.ToDictionary(pair => pair.Key, pair => pair.Value); - else if (performContextAccessor.PerformContext != null) + if (performContextAccessor.PerformContext != null) return performContextAccessor.PerformContext.Items.ToDictionary(pair => pair.Key as object, pair => pair.Value); - else - throw new InvalidOperationException(); + throw new InvalidOperationException(); } } @@ -38,19 +42,22 @@ public object SyncRoot { get { + if (localContextAccessor.Context != null) + return localContextAccessor.Context.Items; if (httpContextAccessor.HttpContext != null) return httpContextAccessor.HttpContext.Items; - else if (performContextAccessor.PerformContext != null) + if (performContextAccessor.PerformContext != null) return performContextAccessor.PerformContext.Items; - else - throw new InvalidOperationException(); + throw new InvalidOperationException(); } } // Methods. public void AddItem(string key, object value) { - if (httpContextAccessor.HttpContext != null) + if (localContextAccessor.Context != null) + localContextAccessor.Context.Items.Add(key, value); + else if (httpContextAccessor.HttpContext != null) httpContextAccessor.HttpContext.Items.Add(key, value); else if (performContextAccessor.PerformContext != null) performContextAccessor.PerformContext.Items.Add(key, value); @@ -60,7 +67,9 @@ public void AddItem(string key, object value) public bool RemoveItem(string key) { - if (httpContextAccessor.HttpContext != null) + if (localContextAccessor.Context != null) + return localContextAccessor.Context.Items.Remove(key); + else if (httpContextAccessor.HttpContext != null) return httpContextAccessor.HttpContext.Items.Remove(key); else if (performContextAccessor.PerformContext != null) return performContextAccessor.PerformContext.Items.Remove(key); diff --git a/src/MongoDM/Utility/DBMaintainer.cs b/src/MongoDM/Utility/DBMaintainer.cs index d8c5cab7..48ebaecb 100644 --- a/src/MongoDM/Utility/DBMaintainer.cs +++ b/src/MongoDM/Utility/DBMaintainer.cs @@ -32,7 +32,7 @@ public void OnUpdatedModel(IAuditable updatedModel, TKey modelId) foreach (var dependencyGroup in dependencies.GroupBy(d => d.RootModelType)) { var idPaths = dependencyGroup - .Select(dependency => string.Join('.', dependency.MemberPathToId.Select(member => member.MemberMap.MemberInfo.Name))) + .Select(dependency => string.Join(".", dependency.MemberPathToId.Select(member => member.MemberMap.MemberInfo.Name))) .Distinct(); // Enqueue call for background job. diff --git a/src/MongoDM/Utility/ILocalContextAccessor.cs b/src/MongoDM/Utility/ILocalContextAccessor.cs new file mode 100644 index 00000000..3fa3bfd3 --- /dev/null +++ b/src/MongoDM/Utility/ILocalContextAccessor.cs @@ -0,0 +1,11 @@ +namespace Digicando.MongoDM.Utility +{ + internal interface ILocalContextAccessor + { + LocalContext Context { get; } + + void OnCreated(LocalContext context); + + void OnDisposed(LocalContext context); + } +} \ No newline at end of file diff --git a/src/MongoDM/Utility/ILocalContextFactory.cs b/src/MongoDM/Utility/ILocalContextFactory.cs new file mode 100644 index 00000000..643860d1 --- /dev/null +++ b/src/MongoDM/Utility/ILocalContextFactory.cs @@ -0,0 +1,9 @@ +using System; + +namespace Digicando.MongoDM.Utility +{ + public interface ILocalContextFactory + { + IDisposable CreateNewLocalContext(); + } +} \ No newline at end of file diff --git a/src/MongoDM/Utility/LocalContext.cs b/src/MongoDM/Utility/LocalContext.cs new file mode 100644 index 00000000..f23f1f14 --- /dev/null +++ b/src/MongoDM/Utility/LocalContext.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; + +namespace Digicando.MongoDM.Utility +{ + public class LocalContext : IDisposable + { + // Fields. + private readonly ILocalContextAccessor localContextAccessor; + + // Constructors. + internal LocalContext(ILocalContextAccessor localContextAccessor) + { + this.localContextAccessor = localContextAccessor; + localContextAccessor.OnCreated(this); + } + + // Properties. + public IDictionary Items { get; } = new Dictionary(); + + public void Dispose() => + localContextAccessor.OnDisposed(this); + } +} diff --git a/src/MongoDM/Utility/LocalContextAccessor.cs b/src/MongoDM/Utility/LocalContextAccessor.cs new file mode 100644 index 00000000..b3a4be62 --- /dev/null +++ b/src/MongoDM/Utility/LocalContextAccessor.cs @@ -0,0 +1,20 @@ +using System.Threading; + +namespace Digicando.MongoDM.Utility +{ + class LocalContextAccessor : ILocalContextAccessor + { + // Fields. + private static readonly AsyncLocal localContextCurrent = new AsyncLocal(); + + // Properties. + public LocalContext Context => localContextCurrent.Value; + + // Methods. + public void OnCreated(LocalContext context) => + localContextCurrent.Value = context; + + public void OnDisposed(LocalContext context) => + localContextCurrent.Value = null; + } +} diff --git a/src/MongoDM/Utility/LocalContextFactory.cs b/src/MongoDM/Utility/LocalContextFactory.cs new file mode 100644 index 00000000..e5340dc6 --- /dev/null +++ b/src/MongoDM/Utility/LocalContextFactory.cs @@ -0,0 +1,18 @@ +using System; + +namespace Digicando.MongoDM.Utility +{ + class LocalContextFactory : ILocalContextFactory + { + private readonly ILocalContextAccessor localContextAccessor; + + public LocalContextFactory( + ILocalContextAccessor localContextAccessor) + { + this.localContextAccessor = localContextAccessor; + } + + public IDisposable CreateNewLocalContext() => + new LocalContext(localContextAccessor); + } +} diff --git a/test/MongoDM.Tests/MongoDM.Tests.csproj b/test/MongoDM.Tests/MongoDM.Tests.csproj index c58ea005..94e0fd60 100644 --- a/test/MongoDM.Tests/MongoDM.Tests.csproj +++ b/test/MongoDM.Tests/MongoDM.Tests.csproj @@ -1,7 +1,7 @@  - netcoreapp2.2 + netcoreapp3.1 true true Digicando.MongoDM @@ -12,12 +12,12 @@ - + all runtime; build; native; contentfiles; analyzers - +