From 969d23d076a0a50f64f8233b04f83a242c4fc0d3 Mon Sep 17 00:00:00 2001 From: zhenlei520 Date: Mon, 14 Mar 2022 14:28:13 +0800 Subject: [PATCH 01/24] feat(EntityFrameworkCore): Adjust MasaDbContextOptions, DbContext, Options support changing life cycle --- .../IModelCreatingProvider.cs | 10 ++++++ .../IQueryFilterProvider.cs | 6 ---- .../MasaDbContext.cs | 35 ++++--------------- .../MasaDbContextOptions.cs | 5 +-- .../MasaDbContextOptionsBuilder.cs | 11 ++++-- .../MasaDbContextOptionsBuilder`.cs | 4 +-- .../MasaDbContextOptions`.cs | 12 +++---- .../ServiceCollectionExtensions.cs | 26 +++++++------- 8 files changed, 47 insertions(+), 62 deletions(-) create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore/IModelCreatingProvider.cs delete mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore/IQueryFilterProvider.cs diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/IModelCreatingProvider.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/IModelCreatingProvider.cs new file mode 100644 index 0000000..66ce20b --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/IModelCreatingProvider.cs @@ -0,0 +1,10 @@ +namespace Masa.Utils.Data.EntityFrameworkCore; + +public interface IModelCreatingProvider +{ + /// + /// + /// + /// + void Configure(ModelBuilder modelBuilder); +} diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/IQueryFilterProvider.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/IQueryFilterProvider.cs deleted file mode 100644 index cacd8e7..0000000 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/IQueryFilterProvider.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Masa.Utils.Data.EntityFrameworkCore; - -public interface IQueryFilterProvider -{ - LambdaExpression OnExecuting(IMutableEntityType entityType); -} diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContext.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContext.cs index b488134..2369561 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContext.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContext.cs @@ -1,16 +1,12 @@ namespace Masa.Utils.Data.EntityFrameworkCore; -public class MasaDbContext : DbContext +public abstract class MasaDbContext : DbContext { private readonly MasaDbContextOptions? _options; public MasaDbContext() { } - public MasaDbContext(MasaDbContextOptions options) - : base(options) - { - _options = options; - } + public MasaDbContext(MasaDbContextOptions options) : base(options) => _options = options; /// /// Automatic filter soft delete data. @@ -29,21 +25,8 @@ protected sealed override void OnModelCreating(ModelBuilder modelBuilder) return; } - foreach (var entityType in modelBuilder.Model.GetEntityTypes()) - { - foreach (var provider in _options.QueryFilterProviders) - { - try - { - var lambda = provider.OnExecuting(entityType); - modelBuilder.Entity(entityType.ClrType).HasQueryFilter(lambda); - } - catch (Exception ex) - { - throw new Exception("An error occured when QueryFilterProvider executing", ex); - } - } - } + foreach (var provider in _options.ModelCreatingProviders) + provider.Configure(modelBuilder); } /// @@ -52,7 +35,6 @@ protected sealed override void OnModelCreating(ModelBuilder modelBuilder) /// protected virtual void OnModelCreatingExecuting(ModelBuilder modelBuilder) { - } /// @@ -60,10 +42,7 @@ protected virtual void OnModelCreatingExecuting(ModelBuilder modelBuilder) /// /// /// - public override int SaveChanges() - { - return SaveChanges(true); - } + public override int SaveChanges() => SaveChanges(true); /// /// Automatic soft delete. @@ -102,9 +81,7 @@ private void OnFilterExecuting() /// /// public override Task SaveChangesAsync(CancellationToken cancellationToken = default) - { - return SaveChangesAsync(true, cancellationToken); - } + => SaveChangesAsync(true, cancellationToken); /// /// Automatic soft delete. diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptions.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptions.cs index deed31f..4b245da 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptions.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptions.cs @@ -16,10 +16,7 @@ public MasaDbContextOptions([NotNull] IReadOnlyDictionary - /// Can be used to filter data - /// - public abstract IEnumerable QueryFilterProviders { get; } + public abstract IEnumerable ModelCreatingProviders { get; } /// /// Can be used to intercept SaveChanges(Async) method diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptionsBuilder.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptionsBuilder.cs index 9f94683..6fff5a6 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptionsBuilder.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptionsBuilder.cs @@ -5,11 +5,16 @@ public abstract class MasaDbContextOptionsBuilder : DbContextOptionsBuilder public MasaDbContextOptionsBuilder(DbContextOptions options) : base(options) { - + ContextLifetime = ServiceLifetime.Scoped; + OptionsLifetime = ServiceLifetime.Scoped; } - public abstract MasaDbContextOptionsBuilder UseQueryFilterProvider() - where TProvider : class, IQueryFilterProvider; + public ServiceLifetime ContextLifetime { get; set; } + + public ServiceLifetime OptionsLifetime { get; set; } + + public abstract MasaDbContextOptionsBuilder UseModelCreatingProvider(ServiceLifetime serviceLifetime = ServiceLifetime.Singleton) + where TProvider : class, IModelCreatingProvider; public abstract MasaDbContextOptionsBuilder UseSaveChangesFilter() where TFilter : class, ISaveChangesFilter; diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptionsBuilder`.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptionsBuilder`.cs index 84a2d18..80880d1 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptionsBuilder`.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptionsBuilder`.cs @@ -11,9 +11,9 @@ public MasaDbContextOptionsBuilder(IServiceCollection services) _services = services; } - public override MasaDbContextOptionsBuilder UseQueryFilterProvider() + public override MasaDbContextOptionsBuilder UseModelCreatingProvider(ServiceLifetime serviceLifetime = ServiceLifetime.Singleton) { - _services.AddScoped(); + _services.TryAddEnumerable(new ServiceDescriptor(typeof(IModelCreatingProvider), typeof(TProvider), serviceLifetime)); return this; } diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptions`.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptions`.cs index a453d45..16f3d5d 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptions`.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptions`.cs @@ -3,22 +3,23 @@ namespace Masa.Utils.Data.EntityFrameworkCore; public class MasaDbContextOptions : MasaDbContextOptions where TContext : MasaDbContext { + public readonly IServiceProvider ServiceProvider; private readonly DbContextOptions _originOptions; public MasaDbContextOptions( DbContextOptions originOptions, - IEnumerable queryFilterProviders, - IEnumerable saveChangesFilters) + IServiceProvider serviceProvider) { + ServiceProvider = serviceProvider; _originOptions = originOptions; - QueryFilterProviders = queryFilterProviders; - SaveChangesFilters = saveChangesFilters; + ModelCreatingProviders = ServiceProvider.GetServices(); + SaveChangesFilters = ServiceProvider.GetServices(); } /// /// Can be used to filter data /// - public override IEnumerable QueryFilterProviders { get; } + public override IEnumerable ModelCreatingProviders { get; } /// /// Can be used to intercept SaveChanges(Async) method @@ -79,4 +80,3 @@ public override TExtension GetExtension() return _originOptions.GetExtension(); } } - diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/ServiceCollectionExtensions.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/ServiceCollectionExtensions.cs index ff905c3..b443e1f 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/ServiceCollectionExtensions.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/ServiceCollectionExtensions.cs @@ -10,21 +10,23 @@ public static IServiceCollection AddMasaDbContext( var builder = new MasaDbContextOptionsBuilder(services); options?.Invoke(builder); - services.AddDbContext(); + services.AddDbContext(builder.ContextLifetime, builder.OptionsLifetime); - services.TryAddScoped(typeof(MasaDbContextOptions), serviceProvider => CreateMasaDbContextOptions(serviceProvider, builder.Options)); - services.TryAddScoped(serviceProvider => serviceProvider.GetRequiredService>()); - - return services; + return services + .TryAdd(typeof(MasaDbContextOptions), + serviceProvider => CreateMasaDbContextOptions(serviceProvider, builder.Options), builder.OptionsLifetime) + .TryAdd(typeof(MasaDbContextOptions), serviceProvider => serviceProvider.GetRequiredService>(), + builder.OptionsLifetime); } - private static MasaDbContextOptions CreateMasaDbContextOptions( - IServiceProvider serviceProvider, - DbContextOptions options) - where TDbContext : MasaDbContext + private static IServiceCollection TryAdd(this IServiceCollection services, Type serviceType, Func factory, + ServiceLifetime lifetime) { - var queryFilterProviders = serviceProvider.GetServices(); - var saveChangesFilters = serviceProvider.GetServices(); - return new MasaDbContextOptions(options, queryFilterProviders, saveChangesFilters); + var serviceDescriptor = new ServiceDescriptor(serviceType, factory, lifetime); + services.TryAdd(serviceDescriptor); + return services; } + + private static MasaDbContextOptions CreateMasaDbContextOptions(IServiceProvider serviceProvider, + DbContextOptions options) where TDbContext : MasaDbContext => new(options, serviceProvider); } From f0198b258a6bf42b983e7872f7eb84280b58e267 Mon Sep 17 00:00:00 2001 From: zhenlei520 Date: Mon, 14 Mar 2022 16:23:16 +0800 Subject: [PATCH 02/24] Merge branch 'main' of https://github.com/masastack/MASA.Utils into feature/EntityFrameworkCore  Conflicts:  src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptionsBuilder.cs  src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptionsBuilder`.cs --- .../MasaDbContextOptionsBuilder.cs | 11 ++++++----- .../MasaDbContextOptionsBuilder`.cs | 3 +-- .../MasaDbContextOptions`.cs | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptionsBuilder.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptionsBuilder.cs index 4f6c6a1..ec58182 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptionsBuilder.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptionsBuilder.cs @@ -7,16 +7,17 @@ public abstract class MasaDbContextOptionsBuilder : DbContextOptionsBuilder public ServiceLifetime ContextLifetime { get; set; } public ServiceLifetime OptionsLifetime { get; set; } - - public MasaDbContextOptionsBuilder(DbContextOptions options) + + public MasaDbContextOptionsBuilder(IServiceCollection services, DbContextOptions options) : base(options) { + Services = services; ContextLifetime = ServiceLifetime.Scoped; OptionsLifetime = ServiceLifetime.Scoped; - Services = services; } - - public abstract MasaDbContextOptionsBuilder UseModelCreatingProvider(ServiceLifetime serviceLifetime = ServiceLifetime.Singleton) + + public abstract MasaDbContextOptionsBuilder UseModelCreatingProvider( + ServiceLifetime serviceLifetime = ServiceLifetime.Singleton) where TProvider : class, IModelCreatingProvider; public abstract MasaDbContextOptionsBuilder UseSaveChangesFilter() diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptionsBuilder`.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptionsBuilder`.cs index 2a6a818..6f12ef0 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptionsBuilder`.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptionsBuilder`.cs @@ -6,12 +6,11 @@ public class MasaDbContextOptionsBuilder : MasaDbContextOptionsBuilder public MasaDbContextOptionsBuilder(IServiceCollection services) : base(services, new DbContextOptions()) { - } public override MasaDbContextOptionsBuilder UseModelCreatingProvider(ServiceLifetime serviceLifetime = ServiceLifetime.Singleton) { - Services.AddScoped(); + Services.Add(new ServiceDescriptor(typeof(IModelCreatingProvider), typeof(TProvider), serviceLifetime)); return this; } diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptions`.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptions`.cs index 16f3d5d..fe79eef 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptions`.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptions`.cs @@ -1,7 +1,7 @@ namespace Masa.Utils.Data.EntityFrameworkCore; public class MasaDbContextOptions : MasaDbContextOptions - where TContext : MasaDbContext + where TContext : DbContext { public readonly IServiceProvider ServiceProvider; private readonly DbContextOptions _originOptions; From 4b84a8e0d0970022589b15f65a2c4efa91d30b7f Mon Sep 17 00:00:00 2001 From: zhenlei520 Date: Thu, 17 Mar 2022 20:03:02 +0800 Subject: [PATCH 03/24] feat(Expression): Extend And and Or methods --- .../ExpressionExtensions.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/Extensions/Masa.Utils.Expressions/ExpressionExtensions.cs b/src/Extensions/Masa.Utils.Expressions/ExpressionExtensions.cs index 8e49b5b..8023984 100644 --- a/src/Extensions/Masa.Utils.Expressions/ExpressionExtensions.cs +++ b/src/Extensions/Masa.Utils.Expressions/ExpressionExtensions.cs @@ -7,11 +7,27 @@ public static Expression> And(this Expression> fi return first.Compose(second, Expression.And); } + public static Expression> And(this Expression> first, bool isCompose, Expression> second) + { + if (isCompose) + return first.Compose(second, Expression.And); + + return first; + } + public static Expression> Or(this Expression> first, Expression> second) { return first.Compose(second, Expression.Or); } + public static Expression> Or(this Expression> first, bool isCompose, Expression> second) + { + if (isCompose) + return first.Compose(second, Expression.Or); + + return first; + } + public static Expression Compose(this Expression first, Expression second, Func merge) { var parameterMap = first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f); From 3b7cc4f9a325cce30e1435d77472215e2ba0ccee Mon Sep 17 00:00:00 2001 From: zhenlei520 Date: Thu, 17 Mar 2022 20:05:02 +0800 Subject: [PATCH 04/24] refactor(EntityFrameworkCode): refactor EntityFramework --- Masa.Utils.sln | 7 ++ ....Data.EntityFrameworkCore.SqlServer.csproj | 17 ++++ .../MasaDbContextOptionsBuilderExtensions.cs | 21 ++++ .../_Imports.cs | 3 + .../DefaultConnectionStringProvider.cs | 12 +++ .../Filters/DataFilter.cs | 64 +++++++++++++ .../Filters/IDataFilter.cs | 10 ++ .../{ => Filters}/ISaveChangesFilter.cs | 2 +- .../Filters/SoftDeleteSaveChangesFilter.cs | 23 +++++ .../IConnectionStringProvider.cs | 8 ++ .../ISoftDelete.cs | 5 + .../Internal/Const.cs | 6 ++ .../Internal/DisposeAction.cs | 10 ++ .../Internal/NullDisposable.cs | 10 ++ ...Masa.Utils.Data.EntityFrameworkCore.csproj | 2 + .../MasaDbConnectionOptions.cs | 11 +++ .../MasaDbContext.cs | 60 ++++++++++-- .../MasaDbContextOptions.cs | 22 ++--- .../MasaDbContextOptionsBuilder.cs | 28 +++--- .../MasaDbContextOptionsBuilder`.cs | 15 +-- .../MasaDbContextOptions`.cs | 5 +- .../ServiceCollectionExtensions.cs | 95 ++++++++++++++++--- .../_Imports.cs | 7 +- 23 files changed, 373 insertions(+), 70 deletions(-) create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.SqlServer/Masa.Utils.Data.EntityFrameworkCore.SqlServer.csproj create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.SqlServer/MasaDbContextOptionsBuilderExtensions.cs create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.SqlServer/_Imports.cs create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore/DefaultConnectionStringProvider.cs create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore/Filters/DataFilter.cs create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore/Filters/IDataFilter.cs rename src/Data/Masa.Utils.Data.EntityFrameworkCore/{ => Filters}/ISaveChangesFilter.cs (62%) create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore/Filters/SoftDeleteSaveChangesFilter.cs create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore/IConnectionStringProvider.cs create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore/ISoftDelete.cs create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore/Internal/Const.cs create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore/Internal/DisposeAction.cs create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore/Internal/NullDisposable.cs create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbConnectionOptions.cs diff --git a/Masa.Utils.sln b/Masa.Utils.sln index ae250ba..62f0267 100644 --- a/Masa.Utils.sln +++ b/Masa.Utils.sln @@ -81,6 +81,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Security.Cryptog EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Caller.Core.Tests", "test\Masa.Utils.Caller.Core.Tests\Masa.Utils.Caller.Core.Tests.csproj", "{4B351F95-5919-46A9-A02F-F4409C9EA79A}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Data.EntityFrameworkCore.SqlServer", "src\Data\Masa.Utils.Data.EntityFrameworkCore.SqlServer\Masa.Utils.Data.EntityFrameworkCore.SqlServer.csproj", "{9004B687-3EB7-4156-A3F7-078A342F2BEF}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -191,6 +193,10 @@ Global {4B351F95-5919-46A9-A02F-F4409C9EA79A}.Debug|Any CPU.Build.0 = Debug|Any CPU {4B351F95-5919-46A9-A02F-F4409C9EA79A}.Release|Any CPU.ActiveCfg = Release|Any CPU {4B351F95-5919-46A9-A02F-F4409C9EA79A}.Release|Any CPU.Build.0 = Release|Any CPU + {9004B687-3EB7-4156-A3F7-078A342F2BEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9004B687-3EB7-4156-A3F7-078A342F2BEF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9004B687-3EB7-4156-A3F7-078A342F2BEF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9004B687-3EB7-4156-A3F7-078A342F2BEF}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -230,6 +236,7 @@ Global {52B3A8FE-A553-4D65-8660-447F120616AB} = {4F908878-0EB8-43E4-96E4-8B1F32E9B635} {1A8FBE3D-B004-4D25-8FE0-A3632A0FDE9E} = {4F908878-0EB8-43E4-96E4-8B1F32E9B635} {4B351F95-5919-46A9-A02F-F4409C9EA79A} = {4F908878-0EB8-43E4-96E4-8B1F32E9B635} + {9004B687-3EB7-4156-A3F7-078A342F2BEF} = {F844C2A1-C36D-400E-A0D8-7658EF9C3B93} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {D7DAA0E6-098F-4B18-8775-64FDA96F1FF0} diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.SqlServer/Masa.Utils.Data.EntityFrameworkCore.SqlServer.csproj b/src/Data/Masa.Utils.Data.EntityFrameworkCore.SqlServer/Masa.Utils.Data.EntityFrameworkCore.SqlServer.csproj new file mode 100644 index 0000000..fc05f07 --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.SqlServer/Masa.Utils.Data.EntityFrameworkCore.SqlServer.csproj @@ -0,0 +1,17 @@ + + + + net6.0 + enable + enable + + + + + + + + + + + diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.SqlServer/MasaDbContextOptionsBuilderExtensions.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore.SqlServer/MasaDbContextOptionsBuilderExtensions.cs new file mode 100644 index 0000000..63e344a --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.SqlServer/MasaDbContextOptionsBuilderExtensions.cs @@ -0,0 +1,21 @@ +namespace Masa.Utils.Data.EntityFrameworkCore.SqlServer; + +public static class MasaDbContextOptionsBuilderExtensions +{ + public static MasaDbContextOptionsBuilder UseSqlServer( + this MasaDbContextOptionsBuilder builder, + Action? sqlServerOptionsAction = null) + { + var connectionStringProvider = builder.ServiceProvider.GetRequiredService(); + return builder.UseSqlServer(connectionStringProvider.GetConnectionString(), sqlServerOptionsAction); + } + + public static MasaDbContextOptionsBuilder UseSqlServer( + this MasaDbContextOptionsBuilder builder, + string connectionString, + Action? sqlServerOptionsAction = null) + { + builder.DbContextOptionsBuilder.UseSqlServer(connectionString, sqlServerOptionsAction); + return builder; + } +} diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.SqlServer/_Imports.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore.SqlServer/_Imports.cs new file mode 100644 index 0000000..c0cb4f2 --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.SqlServer/_Imports.cs @@ -0,0 +1,3 @@ +global using Microsoft.EntityFrameworkCore; +global using Microsoft.EntityFrameworkCore.Infrastructure; +global using Microsoft.Extensions.DependencyInjection; diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/DefaultConnectionStringProvider.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/DefaultConnectionStringProvider.cs new file mode 100644 index 0000000..22d080b --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/DefaultConnectionStringProvider.cs @@ -0,0 +1,12 @@ +namespace Masa.Utils.Data.EntityFrameworkCore; + +public class DefaultConnectionStringProvider : IConnectionStringProvider +{ + private readonly IOptionsSnapshot _options; + + public DefaultConnectionStringProvider(IOptionsSnapshot options) => _options = options; + + public Task GetConnectionStringAsync() => Task.FromResult(GetConnectionString()); + + public string GetConnectionString() => _options.Value.DefaultConnection; +} diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/Filters/DataFilter.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/Filters/DataFilter.cs new file mode 100644 index 0000000..f5c1d9d --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/Filters/DataFilter.cs @@ -0,0 +1,64 @@ +namespace Masa.Utils.Data.EntityFrameworkCore.Filters; + +public class DataFilter : IDataFilter +{ + private readonly IServiceProvider _serviceProvider; + private readonly ConcurrentDictionary _filters; + + public DataFilter(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + _filters = new(); + } + + public IDisposable Enable() where TFilter : class + => GetFilter().Enable(); + + public IDisposable Disable() where TFilter : class + => GetFilter().Disable(); + + public bool IsEnabled() where TFilter : class + => GetFilter().IsEnabled; + + private DataFilter GetFilter() + where TFilter : class + { + return (_filters.GetOrAdd( + typeof(TFilter), + _ => _serviceProvider.GetRequiredService>() + ) as DataFilter)!; + } +} + +public class DataFilter where TFilter : class +{ + private readonly AsyncLocal _filter; + + public DataFilter() + { + _filter = new AsyncLocal { Value = true }; + } + + public bool IsEnabled => _filter.Value; + + public IDisposable Enable() + { + if (IsEnabled) + return NullDisposable.Instance; + + _filter.Value = true; + + return new DisposeAction(() => Disable()); + } + + public IDisposable Disable() + { + if (!IsEnabled) + return NullDisposable.Instance; + + _filter.Value = false; + + return new DisposeAction(() => Enable()); + } + +} diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/Filters/IDataFilter.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/Filters/IDataFilter.cs new file mode 100644 index 0000000..a478e02 --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/Filters/IDataFilter.cs @@ -0,0 +1,10 @@ +namespace Masa.Utils.Data.EntityFrameworkCore.Filters; + +public interface IDataFilter +{ + IDisposable Enable() where TFilter : class; + + IDisposable Disable() where TFilter : class; + + bool IsEnabled() where TFilter : class; +} diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/ISaveChangesFilter.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/Filters/ISaveChangesFilter.cs similarity index 62% rename from src/Data/Masa.Utils.Data.EntityFrameworkCore/ISaveChangesFilter.cs rename to src/Data/Masa.Utils.Data.EntityFrameworkCore/Filters/ISaveChangesFilter.cs index 9f3ae4b..e810fb9 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/ISaveChangesFilter.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/Filters/ISaveChangesFilter.cs @@ -1,4 +1,4 @@ -namespace Masa.Utils.Data.EntityFrameworkCore; +namespace Masa.Utils.Data.EntityFrameworkCore.Filters; public interface ISaveChangesFilter { diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/Filters/SoftDeleteSaveChangesFilter.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/Filters/SoftDeleteSaveChangesFilter.cs new file mode 100644 index 0000000..304d775 --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/Filters/SoftDeleteSaveChangesFilter.cs @@ -0,0 +1,23 @@ +namespace Masa.Utils.Data.EntityFrameworkCore.Filters; + +public class SoftDeleteSaveChangesFilter : ISaveChangesFilter +{ + private readonly MasaDbContextOptions _masaDbContextOptions; + + public SoftDeleteSaveChangesFilter(MasaDbContextOptions masaDbContextOptions) + => _masaDbContextOptions = masaDbContextOptions; + + public void OnExecuting(ChangeTracker changeTracker) + { + if(!_masaDbContextOptions.EnableSoftware) + return; + + changeTracker.DetectChanges(); + foreach (var entity in changeTracker.Entries().Where(entry => entry.State == EntityState.Deleted || + entry.State == EntityState.Added)) + { + entity.State = EntityState.Modified; + entity.CurrentValues[nameof(ISoftDelete.IsDeleted)] = true; + } + } +} diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/IConnectionStringProvider.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/IConnectionStringProvider.cs new file mode 100644 index 0000000..d8748d2 --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/IConnectionStringProvider.cs @@ -0,0 +1,8 @@ +namespace Masa.Utils.Data.EntityFrameworkCore; + +public interface IConnectionStringProvider +{ + Task GetConnectionStringAsync(); + + string GetConnectionString(); +} diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/ISoftDelete.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/ISoftDelete.cs new file mode 100644 index 0000000..da4f6f3 --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/ISoftDelete.cs @@ -0,0 +1,5 @@ +namespace Masa.Utils.Data.EntityFrameworkCore; +public interface ISoftDelete +{ + bool IsDeleted { get; } +} diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/Internal/Const.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/Internal/Const.cs new file mode 100644 index 0000000..026fb75 --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/Internal/Const.cs @@ -0,0 +1,6 @@ +namespace Masa.Utils.Data.EntityFrameworkCore.Internal; + +internal class Const +{ + public const string DefaultSection = "ConnectionStrings"; +} diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/Internal/DisposeAction.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/Internal/DisposeAction.cs new file mode 100644 index 0000000..fe29373 --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/Internal/DisposeAction.cs @@ -0,0 +1,10 @@ +namespace Masa.Utils.Data.EntityFrameworkCore.Internal; + +internal class DisposeAction : IDisposable +{ + private readonly Action _action; + + public DisposeAction(Action action) => _action = action; + + public void Dispose() => _action.Invoke(); +} diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/Internal/NullDisposable.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/Internal/NullDisposable.cs new file mode 100644 index 0000000..8fb4525 --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/Internal/NullDisposable.cs @@ -0,0 +1,10 @@ +namespace Masa.Utils.Data.EntityFrameworkCore.Internal; + +internal class NullDisposable : IDisposable +{ + public static NullDisposable Instance { get; } = new(); + + public void Dispose() + { + } +} diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/Masa.Utils.Data.EntityFrameworkCore.csproj b/src/Data/Masa.Utils.Data.EntityFrameworkCore/Masa.Utils.Data.EntityFrameworkCore.csproj index 31f014e..efd5302 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/Masa.Utils.Data.EntityFrameworkCore.csproj +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/Masa.Utils.Data.EntityFrameworkCore.csproj @@ -8,6 +8,8 @@ + + diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbConnectionOptions.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbConnectionOptions.cs new file mode 100644 index 0000000..54651aa --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbConnectionOptions.cs @@ -0,0 +1,11 @@ +namespace Masa.Utils.Data.EntityFrameworkCore; + +public class MasaDbConnectionOptions +{ + public MasaDbConnectionOptions(string defaultConnection) + { + DefaultConnection = defaultConnection; + } + + public string DefaultConnection { get; private set; } +} diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContext.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContext.cs index 2369561..ecb80bb 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContext.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContext.cs @@ -2,11 +2,14 @@ namespace Masa.Utils.Data.EntityFrameworkCore; public abstract class MasaDbContext : DbContext { - private readonly MasaDbContextOptions? _options; + protected readonly IDataFilter? DataFilter; + protected readonly MasaDbContextOptions? Options; - public MasaDbContext() { } - - public MasaDbContext(MasaDbContextOptions options) : base(options) => _options = options; + public MasaDbContext(MasaDbContextOptions options) : base(options) + { + Options = options; + DataFilter = options.ServiceProvider.GetService(); + } /// /// Automatic filter soft delete data. @@ -16,16 +19,18 @@ public MasaDbContext() { } /// protected sealed override void OnModelCreating(ModelBuilder modelBuilder) { + GlobalSoftwareFilters(modelBuilder); + OnModelCreatingExecuting(modelBuilder); // null when run dotnet ef cli - if (_options == null) + if (Options == null) { base.OnModelCreating(modelBuilder); return; } - foreach (var provider in _options.ModelCreatingProviders) + foreach (var provider in Options.ModelCreatingProviders) provider.Configure(modelBuilder); } @@ -35,8 +40,47 @@ protected sealed override void OnModelCreating(ModelBuilder modelBuilder) /// protected virtual void OnModelCreatingExecuting(ModelBuilder modelBuilder) { + + } + + protected virtual void GlobalSoftwareFilters(ModelBuilder modelBuilder) + { + var methodInfo = typeof(MasaDbContext).GetMethod(nameof(ConfigureGlobalSoftwareFilters), + BindingFlags.NonPublic | BindingFlags.Instance); + + foreach (var entityType in modelBuilder.Model.GetEntityTypes()) + { + methodInfo!.MakeGenericMethod(entityType.ClrType).Invoke(this, new object?[] { modelBuilder, entityType }); + } + } + + private void ConfigureGlobalSoftwareFilters(ModelBuilder modelBuilder, IMutableEntityType mutableEntityType) + where TEntity : class + { + if (mutableEntityType.BaseType == null) + { + var filterExpression = CreateFilterExpression(); + if (filterExpression != null) + modelBuilder.Entity().HasQueryFilter(filterExpression); + } + } + + private Expression>? CreateFilterExpression() + where TEntity : class + { + Expression>? expression = null; + + if (typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity))) + { + expression = entity => !IsSoftDeleteFilterEnabled || + !EF.Property(entity, nameof(ISoftDelete.IsDeleted)); + } + + return expression; } + protected virtual bool IsSoftDeleteFilterEnabled => Options.EnableSoftware && (DataFilter?.IsEnabled() ?? false); + /// /// Automatic soft delete. /// @@ -58,9 +102,9 @@ public sealed override int SaveChanges(bool acceptAllChangesOnSuccess) private void OnFilterExecuting() { - if (_options != null) + if (Options != null) { - foreach (var filter in _options.SaveChangesFilters) + foreach (var filter in Options.SaveChangesFilters) { try { diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptions.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptions.cs index 4b245da..38cf38d 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptions.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptions.cs @@ -2,19 +2,7 @@ namespace Masa.Utils.Data.EntityFrameworkCore; public abstract class MasaDbContextOptions : DbContextOptions { - [SuppressMessage("Usage", "EF1001:Internal EF Core API usage.")] - public MasaDbContextOptions() - : base(new Dictionary()) - { - - } - - [SuppressMessage("Usage", "EF1001:Internal EF Core API usage.")] - public MasaDbContextOptions([NotNull] IReadOnlyDictionary extensions) - : base(extensions) - { - - } + public readonly IServiceProvider ServiceProvider; public abstract IEnumerable ModelCreatingProviders { get; } @@ -22,4 +10,12 @@ public MasaDbContextOptions([NotNull] IReadOnlyDictionary public abstract IEnumerable SaveChangesFilters { get; } + + public bool EnableSoftware { get; } + + protected MasaDbContextOptions(IServiceProvider serviceProvider, bool enableSoftware) + { + ServiceProvider = serviceProvider; + EnableSoftware = enableSoftware; + } } diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptionsBuilder.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptionsBuilder.cs index ec58182..6b5638d 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptionsBuilder.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptionsBuilder.cs @@ -1,25 +1,23 @@ namespace Masa.Utils.Data.EntityFrameworkCore; -public abstract class MasaDbContextOptionsBuilder : DbContextOptionsBuilder +public abstract class MasaDbContextOptionsBuilder { - public readonly IServiceCollection Services; + public DbContextOptionsBuilder DbContextOptionsBuilder; - public ServiceLifetime ContextLifetime { get; set; } + public IServiceProvider ServiceProvider { get; } - public ServiceLifetime OptionsLifetime { get; set; } + internal bool EnableSoftwareDelete { get; private set; } - public MasaDbContextOptionsBuilder(IServiceCollection services, DbContextOptions options) - : base(options) + protected MasaDbContextOptionsBuilder(IServiceProvider serviceProvider, DbContextOptions options, bool enableSoftwareDelete) { - Services = services; - ContextLifetime = ServiceLifetime.Scoped; - OptionsLifetime = ServiceLifetime.Scoped; + DbContextOptionsBuilder = new DbContextOptionsBuilder(options); + ServiceProvider = serviceProvider; + EnableSoftwareDelete = enableSoftwareDelete; } - public abstract MasaDbContextOptionsBuilder UseModelCreatingProvider( - ServiceLifetime serviceLifetime = ServiceLifetime.Singleton) - where TProvider : class, IModelCreatingProvider; - - public abstract MasaDbContextOptionsBuilder UseSaveChangesFilter() - where TFilter : class, ISaveChangesFilter; + public MasaDbContextOptionsBuilder UseSoftDelete() + { + EnableSoftwareDelete = true; + return this; + } } diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptionsBuilder`.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptionsBuilder`.cs index 6f12ef0..7f7ea27 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptionsBuilder`.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptionsBuilder`.cs @@ -3,20 +3,7 @@ namespace Masa.Utils.Data.EntityFrameworkCore; public class MasaDbContextOptionsBuilder : MasaDbContextOptionsBuilder where TContext : MasaDbContext { - public MasaDbContextOptionsBuilder(IServiceCollection services) - : base(services, new DbContextOptions()) + public MasaDbContextOptionsBuilder(IServiceProvider serviceProvider) : base(serviceProvider, new DbContextOptions(), false) { } - - public override MasaDbContextOptionsBuilder UseModelCreatingProvider(ServiceLifetime serviceLifetime = ServiceLifetime.Singleton) - { - Services.Add(new ServiceDescriptor(typeof(IModelCreatingProvider), typeof(TProvider), serviceLifetime)); - return this; - } - - public override MasaDbContextOptionsBuilder UseSaveChangesFilter() - { - Services.AddScoped(); - return this; - } } diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptions`.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptions`.cs index fe79eef..becfb62 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptions`.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptions`.cs @@ -3,14 +3,13 @@ namespace Masa.Utils.Data.EntityFrameworkCore; public class MasaDbContextOptions : MasaDbContextOptions where TContext : DbContext { - public readonly IServiceProvider ServiceProvider; private readonly DbContextOptions _originOptions; public MasaDbContextOptions( + IServiceProvider serviceProvider, DbContextOptions originOptions, - IServiceProvider serviceProvider) + bool enableSoftware) : base(serviceProvider, enableSoftware) { - ServiceProvider = serviceProvider; _originOptions = originOptions; ModelCreatingProviders = ServiceProvider.GetServices(); SaveChangesFilters = ServiceProvider.GetServices(); diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/ServiceCollectionExtensions.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/ServiceCollectionExtensions.cs index b443e1f..0a40776 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/ServiceCollectionExtensions.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/ServiceCollectionExtensions.cs @@ -1,32 +1,97 @@ +using Microsoft.Extensions.Configuration; + namespace Masa.Utils.Data.EntityFrameworkCore; public static class ServiceCollectionExtensions { public static IServiceCollection AddMasaDbContext( this IServiceCollection services, - Action? options = null) + Action? optionsAction = null, + ServiceLifetime contextLifetime = ServiceLifetime.Scoped, + ServiceLifetime optionsLifetime = ServiceLifetime.Scoped) + where TDbContext : MasaDbContext + => services.AddMasaDbContext( + (_, masaDbContextOptionsBuilder) => optionsAction?.Invoke(masaDbContextOptionsBuilder), + contextLifetime, + optionsLifetime); + + public static IServiceCollection AddMasaDbContext( + this IServiceCollection services, + Action? optionsAction = null, + ServiceLifetime contextLifetime = ServiceLifetime.Scoped, + ServiceLifetime optionsLifetime = ServiceLifetime.Scoped) where TDbContext : MasaDbContext + => services + .AddDbContext(contextLifetime, optionsLifetime) + .AddCoreServices(optionsAction, optionsLifetime); + + private static IServiceCollection AddCoreServices( + this IServiceCollection services, + Action? optionsAction, + ServiceLifetime optionsLifetime) + where TDbContextImplementation : MasaDbContext { - var builder = new MasaDbContextOptionsBuilder(services); - options?.Invoke(builder); + services.TryAddConfigure(); + services.TryAddScoped(); + services.TryAddScoped(typeof(DataFilter<>)); + services.TryAddScoped(); + services.TryAddEnumerable(new ServiceDescriptor(typeof(ISaveChangesFilter), typeof(SoftDeleteSaveChangesFilter), + ServiceLifetime.Scoped)); - services.AddDbContext(builder.ContextLifetime, builder.OptionsLifetime); + services.TryAdd( + new ServiceDescriptor( + typeof(MasaDbContextOptions), + serviceProvider => CreateMasaDbContextOptions(serviceProvider, optionsAction), + optionsLifetime)); - return services - .TryAdd(typeof(MasaDbContextOptions), - serviceProvider => CreateMasaDbContextOptions(serviceProvider, builder.Options), builder.OptionsLifetime) - .TryAdd(typeof(MasaDbContextOptions), serviceProvider => serviceProvider.GetRequiredService>(), - builder.OptionsLifetime); + services.Add( + new ServiceDescriptor( + typeof(MasaDbContextOptions), + serviceProvider => serviceProvider.GetRequiredService>(), + optionsLifetime)); + return services; } - private static IServiceCollection TryAdd(this IServiceCollection services, Type serviceType, Func factory, - ServiceLifetime lifetime) + private static MasaDbContextOptions CreateMasaDbContextOptions( + IServiceProvider serviceProvider, + Action? optionsAction) + where TDbContext : MasaDbContext { - var serviceDescriptor = new ServiceDescriptor(serviceType, factory, lifetime); - services.TryAdd(serviceDescriptor); - return services; + var masaDbContextOptionsBuilder = new MasaDbContextOptionsBuilder(serviceProvider); + optionsAction?.Invoke(serviceProvider, masaDbContextOptionsBuilder); + + return CreateMasaDbContextOptions( + serviceProvider, + masaDbContextOptionsBuilder.DbContextOptionsBuilder.Options, + masaDbContextOptionsBuilder.EnableSoftwareDelete); } private static MasaDbContextOptions CreateMasaDbContextOptions(IServiceProvider serviceProvider, - DbContextOptions options) where TDbContext : MasaDbContext => new(options, serviceProvider); + DbContextOptions options, bool enableSoftware) where TDbContext : MasaDbContext => new(serviceProvider, options, enableSoftware); + + private static IServiceCollection TryAddConfigure( + this IServiceCollection services) + where TOptions : class + => services.TryAddConfigure(Const.DefaultSection); + + private static IServiceCollection TryAddConfigure( + this IServiceCollection services, + string sectionName) + where TOptions : class + { + IConfiguration? configuration = services.BuildServiceProvider().GetService(); + if (configuration == null) + return services; + + string name = typeof(TOptions).FullName ?? typeof(TOptions).Name; + services.AddOptions(); + var configurationSection = configuration.GetSection(sectionName); + services.TryAddSingleton>( + new ConfigurationChangeTokenSource(name, configurationSection)); + services.TryAddSingleton>(new NamedConfigureFromConfigurationOptions(name, + configurationSection, _ => + { + })); + return services; + } } diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/_Imports.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/_Imports.cs index 3636c7b..1058752 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/_Imports.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/_Imports.cs @@ -1,8 +1,13 @@ +global using Masa.Utils.Data.EntityFrameworkCore.Filters; +global using Masa.Utils.Data.EntityFrameworkCore.Internal; global using Microsoft.EntityFrameworkCore; global using Microsoft.EntityFrameworkCore.ChangeTracking; global using Microsoft.EntityFrameworkCore.Infrastructure; global using Microsoft.EntityFrameworkCore.Metadata; global using Microsoft.Extensions.DependencyInjection; global using Microsoft.Extensions.DependencyInjection.Extensions; -global using System.Diagnostics.CodeAnalysis; +global using Microsoft.Extensions.Options; +global using System.Collections.Concurrent; global using System.Linq.Expressions; +global using System.Reflection; + From 37354a37ccebac244819b985e7260daa3ff116aa Mon Sep 17 00:00:00 2001 From: zhenlei520 Date: Thu, 17 Mar 2022 20:30:51 +0800 Subject: [PATCH 05/24] perf(Expressions): Extend And Or methods --- .../Masa.Utils.Expressions/ExpressionExtensions.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Extensions/Masa.Utils.Expressions/ExpressionExtensions.cs b/src/Extensions/Masa.Utils.Expressions/ExpressionExtensions.cs index 8023984..6d80844 100644 --- a/src/Extensions/Masa.Utils.Expressions/ExpressionExtensions.cs +++ b/src/Extensions/Masa.Utils.Expressions/ExpressionExtensions.cs @@ -7,9 +7,9 @@ public static Expression> And(this Expression> fi return first.Compose(second, Expression.And); } - public static Expression> And(this Expression> first, bool isCompose, Expression> second) + public static Expression> And(this Expression> first, bool isCompose, Expression>? second) { - if (isCompose) + if (isCompose && second != null) return first.Compose(second, Expression.And); return first; @@ -20,9 +20,9 @@ public static Expression> Or(this Expression> fir return first.Compose(second, Expression.Or); } - public static Expression> Or(this Expression> first, bool isCompose, Expression> second) + public static Expression> Or(this Expression> first, bool isCompose, Expression>? second) { - if (isCompose) + if (isCompose && second != null) return first.Compose(second, Expression.Or); return first; @@ -83,7 +83,9 @@ private static List ParseUnitExpression(Expression unitExpression) return result; } + #endregion + } public class ParameterRebinder : ExpressionVisitor From 693ae99c90f3ad4ece99a629800a9d560f3e890a Mon Sep 17 00:00:00 2001 From: zhenlei520 Date: Thu, 17 Mar 2022 20:34:41 +0800 Subject: [PATCH 06/24] refactor(EntityFrameworkCore): Refactor MasaDbContext and add global filters --- .../MasaDbContext.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContext.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContext.cs index 8e20f33..b21998f 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContext.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContext.cs @@ -19,7 +19,7 @@ public MasaDbContext(MasaDbContextOptions options) : base(options) /// protected sealed override void OnModelCreating(ModelBuilder modelBuilder) { - GlobalSoftwareFilters(modelBuilder); + OnModelCreatingConfigureGlobalFilters(modelBuilder); OnModelCreatingExecuting(modelBuilder); @@ -43,9 +43,9 @@ protected virtual void OnModelCreatingExecuting(ModelBuilder modelBuilder) } - protected virtual void GlobalSoftwareFilters(ModelBuilder modelBuilder) + protected virtual void OnModelCreatingConfigureGlobalFilters(ModelBuilder modelBuilder) { - var methodInfo = typeof(MasaDbContext).GetMethod(nameof(ConfigureGlobalSoftwareFilters), + var methodInfo = typeof(MasaDbContext).GetMethod(nameof(ConfigureGlobalFilters), BindingFlags.NonPublic | BindingFlags.Instance); foreach (var entityType in modelBuilder.Model.GetEntityTypes()) @@ -54,7 +54,7 @@ protected virtual void GlobalSoftwareFilters(ModelBuilder modelBuilder) } } - private void ConfigureGlobalSoftwareFilters(ModelBuilder modelBuilder, IMutableEntityType mutableEntityType) + protected virtual void ConfigureGlobalFilters(ModelBuilder modelBuilder, IMutableEntityType mutableEntityType) where TEntity : class { if (mutableEntityType.BaseType == null) @@ -65,7 +65,7 @@ private void ConfigureGlobalSoftwareFilters(ModelBuilder modelBuilder, } } - private Expression>? CreateFilterExpression() + protected virtual Expression>? CreateFilterExpression() where TEntity : class { Expression>? expression = null; From 494f47266f5302f99031c5bb5579b7b306c70c06 Mon Sep 17 00:00:00 2001 From: zhenlei520 Date: Thu, 17 Mar 2022 22:57:43 +0800 Subject: [PATCH 07/24] chore(EntityFrameworkCore): Change parameter names --- .../Filters/SoftDeleteSaveChangesFilter.cs | 2 +- .../MasaDbContext.cs | 2 +- .../MasaDbContextOptions.cs | 6 +++--- .../MasaDbContextOptionsBuilder.cs | 8 ++++---- .../MasaDbContextOptions`.cs | 2 +- .../ServiceCollectionExtensions.cs | 20 +++++++++---------- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/Filters/SoftDeleteSaveChangesFilter.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/Filters/SoftDeleteSaveChangesFilter.cs index 304d775..92f186c 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/Filters/SoftDeleteSaveChangesFilter.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/Filters/SoftDeleteSaveChangesFilter.cs @@ -9,7 +9,7 @@ public SoftDeleteSaveChangesFilter(MasaDbContextOptions masaDbContextOptions) public void OnExecuting(ChangeTracker changeTracker) { - if(!_masaDbContextOptions.EnableSoftware) + if(!_masaDbContextOptions.EnableSoftDelete) return; changeTracker.DetectChanges(); diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContext.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContext.cs index b21998f..692f64a 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContext.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContext.cs @@ -79,7 +79,7 @@ protected virtual void ConfigureGlobalFilters(ModelBuilder modelBuilder return expression; } - protected virtual bool IsSoftDeleteFilterEnabled => (Options?.EnableSoftware ?? false) && (DataFilter?.IsEnabled() ?? false); + protected virtual bool IsSoftDeleteFilterEnabled => (Options?.EnableSoftDelete ?? false) && (DataFilter?.IsEnabled() ?? false); /// /// Automatic soft delete. diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptions.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptions.cs index 38cf38d..4dea55e 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptions.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptions.cs @@ -11,11 +11,11 @@ public abstract class MasaDbContextOptions : DbContextOptions /// public abstract IEnumerable SaveChangesFilters { get; } - public bool EnableSoftware { get; } + public bool EnableSoftDelete { get; } - protected MasaDbContextOptions(IServiceProvider serviceProvider, bool enableSoftware) + protected MasaDbContextOptions(IServiceProvider serviceProvider, bool enableSoftDelete) { ServiceProvider = serviceProvider; - EnableSoftware = enableSoftware; + EnableSoftDelete = enableSoftDelete; } } diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptionsBuilder.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptionsBuilder.cs index 6b5638d..7f44ef2 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptionsBuilder.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptionsBuilder.cs @@ -6,18 +6,18 @@ public abstract class MasaDbContextOptionsBuilder public IServiceProvider ServiceProvider { get; } - internal bool EnableSoftwareDelete { get; private set; } + internal bool EnableSoftDelete { get; private set; } - protected MasaDbContextOptionsBuilder(IServiceProvider serviceProvider, DbContextOptions options, bool enableSoftwareDelete) + protected MasaDbContextOptionsBuilder(IServiceProvider serviceProvider, DbContextOptions options, bool enableSoftDelete) { DbContextOptionsBuilder = new DbContextOptionsBuilder(options); ServiceProvider = serviceProvider; - EnableSoftwareDelete = enableSoftwareDelete; + EnableSoftDelete = enableSoftDelete; } public MasaDbContextOptionsBuilder UseSoftDelete() { - EnableSoftwareDelete = true; + EnableSoftDelete = true; return this; } } diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptions`.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptions`.cs index becfb62..e553ea0 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptions`.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptions`.cs @@ -8,7 +8,7 @@ public class MasaDbContextOptions : MasaDbContextOptions public MasaDbContextOptions( IServiceProvider serviceProvider, DbContextOptions originOptions, - bool enableSoftware) : base(serviceProvider, enableSoftware) + bool enableSoftDelete) : base(serviceProvider, enableSoftDelete) { _originOptions = originOptions; ModelCreatingProviders = ServiceProvider.GetServices(); diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/ServiceCollectionExtensions.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/ServiceCollectionExtensions.cs index 0a40776..c4e69fa 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/ServiceCollectionExtensions.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/ServiceCollectionExtensions.cs @@ -6,28 +6,28 @@ public static class ServiceCollectionExtensions { public static IServiceCollection AddMasaDbContext( this IServiceCollection services, - Action? optionsAction = null, + Action? optionsBuilder = null, ServiceLifetime contextLifetime = ServiceLifetime.Scoped, ServiceLifetime optionsLifetime = ServiceLifetime.Scoped) where TDbContext : MasaDbContext => services.AddMasaDbContext( - (_, masaDbContextOptionsBuilder) => optionsAction?.Invoke(masaDbContextOptionsBuilder), + (_, masaDbContextOptionsBuilder) => optionsBuilder?.Invoke(masaDbContextOptionsBuilder), contextLifetime, optionsLifetime); public static IServiceCollection AddMasaDbContext( this IServiceCollection services, - Action? optionsAction = null, + Action? optionsBuilder = null, ServiceLifetime contextLifetime = ServiceLifetime.Scoped, ServiceLifetime optionsLifetime = ServiceLifetime.Scoped) where TDbContext : MasaDbContext => services .AddDbContext(contextLifetime, optionsLifetime) - .AddCoreServices(optionsAction, optionsLifetime); + .AddCoreServices(optionsBuilder, optionsLifetime); private static IServiceCollection AddCoreServices( this IServiceCollection services, - Action? optionsAction, + Action? optionsBuilder, ServiceLifetime optionsLifetime) where TDbContextImplementation : MasaDbContext { @@ -41,7 +41,7 @@ private static IServiceCollection AddCoreServices( services.TryAdd( new ServiceDescriptor( typeof(MasaDbContextOptions), - serviceProvider => CreateMasaDbContextOptions(serviceProvider, optionsAction), + serviceProvider => CreateMasaDbContextOptions(serviceProvider, optionsBuilder), optionsLifetime)); services.Add( @@ -54,20 +54,20 @@ private static IServiceCollection AddCoreServices( private static MasaDbContextOptions CreateMasaDbContextOptions( IServiceProvider serviceProvider, - Action? optionsAction) + Action? optionsBuilder) where TDbContext : MasaDbContext { var masaDbContextOptionsBuilder = new MasaDbContextOptionsBuilder(serviceProvider); - optionsAction?.Invoke(serviceProvider, masaDbContextOptionsBuilder); + optionsBuilder?.Invoke(serviceProvider, masaDbContextOptionsBuilder); return CreateMasaDbContextOptions( serviceProvider, masaDbContextOptionsBuilder.DbContextOptionsBuilder.Options, - masaDbContextOptionsBuilder.EnableSoftwareDelete); + masaDbContextOptionsBuilder.EnableSoftDelete); } private static MasaDbContextOptions CreateMasaDbContextOptions(IServiceProvider serviceProvider, - DbContextOptions options, bool enableSoftware) where TDbContext : MasaDbContext => new(serviceProvider, options, enableSoftware); + DbContextOptions options, bool enableSoftDelete) where TDbContext : MasaDbContext => new(serviceProvider, options, enableSoftDelete); private static IServiceCollection TryAddConfigure( this IServiceCollection services) From 743d5d24223b5f4a23d28b4ddf9a7e65df7b7693 Mon Sep 17 00:00:00 2001 From: zhenlei520 Date: Thu, 17 Mar 2022 22:58:10 +0800 Subject: [PATCH 08/24] docs(EntityFrameworkCore): add EntityFrameworkCore doc --- .../README.md | 33 +++++++++++++++ .../README.zh-CN.md | 33 +++++++++++++++ .../README.md | 40 +++++++++++++++++++ .../README.zh-CN.md | 40 +++++++++++++++++++ 4 files changed, 146 insertions(+) create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.SqlServer/README.md create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.SqlServer/README.zh-CN.md create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore/README.md create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore/README.zh-CN.md diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.SqlServer/README.md b/src/Data/Masa.Utils.Data.EntityFrameworkCore.SqlServer/README.md new file mode 100644 index 0000000..0a5ebb8 --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.SqlServer/README.md @@ -0,0 +1,33 @@ +[中](README.zh-CN.md) | EN + +## Masa.Utils.Data.EntityFrameworkCore.SqlServer + +## Example: + +```c# +Install-Package Masa.Utils.Data.EntityFrameworkCore.SqlServer +``` + +##### Usage 1: + +1. Configure appsettings.json + +``` appsettings.json +{ + "ConnectionStrings": { + "DefaultConnection": "server=localhost;uid=sa;pwd=P@ssw0rd;database=identity" + } +} +``` + +2. Using MasaDbContext + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseSqlServer()); +``` + +##### Usage 2: + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseSqlServer("server=localhost;uid=sa;pwd=P@ssw0rd;database=identity")); +``` \ No newline at end of file diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.SqlServer/README.zh-CN.md b/src/Data/Masa.Utils.Data.EntityFrameworkCore.SqlServer/README.zh-CN.md new file mode 100644 index 0000000..7b1a86e --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.SqlServer/README.zh-CN.md @@ -0,0 +1,33 @@ +中 | [EN](README.md) + +## Masa.Utils.Data.EntityFrameworkCore.SqlServer + +## 用例: + +```c# +Install-Package Masa.Utils.Data.EntityFrameworkCore.SqlServer +``` + +#### 用法1: + +1. 配置appsettings.json + +``` appsettings.json +{ + "ConnectionStrings": { + "DefaultConnection": "server=localhost;uid=sa;pwd=P@ssw0rd;database=identity" + } +} +``` + +2. 使用MasaDbContext + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseSqlServer()); +``` + +#### 用法2: + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseSqlServer("server=localhost;uid=sa;pwd=P@ssw0rd;database=identity")); +``` \ No newline at end of file diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/README.md b/src/Data/Masa.Utils.Data.EntityFrameworkCore/README.md new file mode 100644 index 0000000..3305ecf --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/README.md @@ -0,0 +1,40 @@ +[中](README.zh-CN.md) | EN + +## Masa.Utils.Data.EntityFrameworkCore + +## Example: + +```c# +Install-Package Masa.Utils.Data.EntityFrameworkCore +Install-Package Microsoft.EntityFrameworkCore.SqlServer +``` + +#### Basic usage: + +Using MasaDbContext + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => +{ + optionsBuilder.UseSoftDelete();//enable soft delete + optionsBuilder.DbContextOptionsBuilder.UseSqlServer("server=localhost;uid=sa;pwd=P@ssw0rd;database=identity"); +}); +``` + +Recommended usage: + +[SqlServer](../Masa.Utils.Data.EntityFrameworkCore.SqlServer/README.md) + +#### data filter + +``` C# +public async Task GetAllAsync([FromServices] IRepository repository, [FromServices] IDataFilter dataFilter) +{ + // Temporarily disable soft delete filtering + using (dataFilter.Disable()) + { + var list = (await repository.GetListAsync()).ToList(); + return System.Text.Json.JsonSerializer.Serialize(list); + } +} +``` \ No newline at end of file diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/README.zh-CN.md b/src/Data/Masa.Utils.Data.EntityFrameworkCore/README.zh-CN.md new file mode 100644 index 0000000..c9e86de --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/README.zh-CN.md @@ -0,0 +1,40 @@ +中 | [EN](README.md) + +## Masa.Utils.Data.EntityFrameworkCore + +## 用例: + +```c# +Install-Package Masa.Utils.Data.EntityFrameworkCore +Install-Package Microsoft.EntityFrameworkCore.SqlServer +``` + +#### 基本用法: + +使用MasaDbContext + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => +{ + optionsBuilder.UseSoftDelete();//启用软删除 + optionsBuilder.DbContextOptionsBuilder.UseSqlServer("server=localhost;uid=sa;pwd=P@ssw0rd;database=identity"); +}); +``` + +推荐用法: + +[SqlServer](../Masa.Utils.Data.EntityFrameworkCore.SqlServer/README.zh-CN.md) + +#### 数据过滤器 + +``` C# +public async Task GetAllAsync([FromServices] IRepository repository, [FromServices] IDataFilter dataFilter) +{ + // 临时禁用软删除过滤 + using (dataFilter.Disable()) + { + var list = (await repository.GetListAsync()).ToList(); + return System.Text.Json.JsonSerializer.Serialize(list); + } +} +``` \ No newline at end of file From 84ca8578931571d6bb806792847158e95ab63bba Mon Sep 17 00:00:00 2001 From: zhenlei520 Date: Thu, 17 Mar 2022 23:40:30 +0800 Subject: [PATCH 09/24] chore(EntityFramework.SqlServer): change file encoding --- .../MasaDbContextOptionsBuilderExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.SqlServer/MasaDbContextOptionsBuilderExtensions.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore.SqlServer/MasaDbContextOptionsBuilderExtensions.cs index 63e344a..514f3c2 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore.SqlServer/MasaDbContextOptionsBuilderExtensions.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.SqlServer/MasaDbContextOptionsBuilderExtensions.cs @@ -1,4 +1,4 @@ -namespace Masa.Utils.Data.EntityFrameworkCore.SqlServer; +namespace Masa.Utils.Data.EntityFrameworkCore.SqlServer; public static class MasaDbContextOptionsBuilderExtensions { From 3806f5f28034bab95c4609edc9ef8ca2439deaec Mon Sep 17 00:00:00 2001 From: zhenlei520 Date: Thu, 17 Mar 2022 23:42:05 +0800 Subject: [PATCH 10/24] feat(EntityFrameworkCore.InMemory): support EntityFrameworkCore.InMemory --- ...s.Data.EntityFrameworkCore.InMemory.csproj | 17 ++++++++++ .../MasaDbContextOptionsBuilderExtensions.cs | 21 ++++++++++++ .../README.md | 33 +++++++++++++++++++ .../README.zh-CN.md | 33 +++++++++++++++++++ .../_Imports.cs | 3 ++ 5 files changed, 107 insertions(+) create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.InMemory/Masa.Utils.Data.EntityFrameworkCore.InMemory.csproj create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.InMemory/MasaDbContextOptionsBuilderExtensions.cs create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.InMemory/README.md create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.InMemory/README.zh-CN.md create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.InMemory/_Imports.cs diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.InMemory/Masa.Utils.Data.EntityFrameworkCore.InMemory.csproj b/src/Data/Masa.Utils.Data.EntityFrameworkCore.InMemory/Masa.Utils.Data.EntityFrameworkCore.InMemory.csproj new file mode 100644 index 0000000..b4048df --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.InMemory/Masa.Utils.Data.EntityFrameworkCore.InMemory.csproj @@ -0,0 +1,17 @@ + + + + net6.0 + enable + enable + + + + + + + + + + + diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.InMemory/MasaDbContextOptionsBuilderExtensions.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore.InMemory/MasaDbContextOptionsBuilderExtensions.cs new file mode 100644 index 0000000..3120b0a --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.InMemory/MasaDbContextOptionsBuilderExtensions.cs @@ -0,0 +1,21 @@ +namespace Masa.Utils.Data.EntityFrameworkCore.InMemory; + +public static class MasaDbContextOptionsBuilderExtensions +{ + public static MasaDbContextOptionsBuilder UseInMemoryDatabase( + this MasaDbContextOptionsBuilder builder, + Action? inMemoryOptionsAction = null) + { + var connectionStringProvider = builder.ServiceProvider.GetRequiredService(); + return builder.UseInMemoryDatabase(connectionStringProvider.GetConnectionString(), inMemoryOptionsAction); + } + + public static MasaDbContextOptionsBuilder UseInMemoryDatabase( + this MasaDbContextOptionsBuilder builder, + string databaseName, + Action? inMemoryOptionsAction = null) + { + builder.DbContextOptionsBuilder.UseInMemoryDatabase(databaseName, inMemoryOptionsAction); + return builder; + } +} diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.InMemory/README.md b/src/Data/Masa.Utils.Data.EntityFrameworkCore.InMemory/README.md new file mode 100644 index 0000000..17a9f1a --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.InMemory/README.md @@ -0,0 +1,33 @@ +[中](README.zh-CN.md) | EN + +## Masa.Utils.Data.EntityFrameworkCore.InMemory + +## Example: + +```c# +Install-Package Masa.Utils.Data.EntityFrameworkCore.InMemory +``` + +##### Usage 1: + +1. Configure appsettings.json + +``` appsettings.json +{ + "ConnectionStrings": { + "DefaultConnection": "identity" + } +} +``` + +2. Using MasaDbContext + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseInMemoryDatabase()); +``` + +##### Usage 2: + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseInMemoryDatabase("identity")); +``` \ No newline at end of file diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.InMemory/README.zh-CN.md b/src/Data/Masa.Utils.Data.EntityFrameworkCore.InMemory/README.zh-CN.md new file mode 100644 index 0000000..015ba20 --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.InMemory/README.zh-CN.md @@ -0,0 +1,33 @@ +中 | [EN](README.md) + +## Masa.Utils.Data.EntityFrameworkCore.InMemory + +## 用例: + +```c# +Install-Package Masa.Utils.Data.EntityFrameworkCore.InMemory +``` + +#### 用法1: + +1. 配置appsettings.json + +``` appsettings.json +{ + "ConnectionStrings": { + "DefaultConnection": "identity" + } +} +``` + +2. 使用MasaDbContext + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseInMemoryDatabase()); +``` + +#### 用法2: + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseInMemoryDatabase("identity")); +``` \ No newline at end of file diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.InMemory/_Imports.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore.InMemory/_Imports.cs new file mode 100644 index 0000000..c0cb4f2 --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.InMemory/_Imports.cs @@ -0,0 +1,3 @@ +global using Microsoft.EntityFrameworkCore; +global using Microsoft.EntityFrameworkCore.Infrastructure; +global using Microsoft.Extensions.DependencyInjection; From c0a73f5fd70e02d14ee58720b115bac8d3c77a73 Mon Sep 17 00:00:00 2001 From: zhenlei520 Date: Thu, 17 Mar 2022 23:44:07 +0800 Subject: [PATCH 11/24] feat(EntityFrameworkCore.MySql): support EntityFrameworkCore.MySql --- ...tils.Data.EntityFrameworkCore.MySql.csproj | 17 ++++++++++ .../MasaDbContextOptionsBuilderExtensions.cs | 21 ++++++++++++ .../README.md | 33 +++++++++++++++++++ .../README.zh-CN.md | 33 +++++++++++++++++++ .../_Imports.cs | 3 ++ 5 files changed, 107 insertions(+) create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.MySql/Masa.Utils.Data.EntityFrameworkCore.MySql.csproj create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.MySql/MasaDbContextOptionsBuilderExtensions.cs create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.MySql/README.md create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.MySql/README.zh-CN.md create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.MySql/_Imports.cs diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.MySql/Masa.Utils.Data.EntityFrameworkCore.MySql.csproj b/src/Data/Masa.Utils.Data.EntityFrameworkCore.MySql/Masa.Utils.Data.EntityFrameworkCore.MySql.csproj new file mode 100644 index 0000000..4b9430c --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.MySql/Masa.Utils.Data.EntityFrameworkCore.MySql.csproj @@ -0,0 +1,17 @@ + + + + net6.0 + enable + enable + + + + + + + + + + + diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.MySql/MasaDbContextOptionsBuilderExtensions.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore.MySql/MasaDbContextOptionsBuilderExtensions.cs new file mode 100644 index 0000000..028dab2 --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.MySql/MasaDbContextOptionsBuilderExtensions.cs @@ -0,0 +1,21 @@ +namespace Masa.Utils.Data.EntityFrameworkCore.MySql; + +public static class MasaDbContextOptionsBuilderExtensions +{ + public static MasaDbContextOptionsBuilder UseMySQL( + this MasaDbContextOptionsBuilder builder, + Action? mySQLOptionsAction = null) + { + var connectionStringProvider = builder.ServiceProvider.GetRequiredService(); + return builder.UseMySQL(connectionStringProvider.GetConnectionString(), mySQLOptionsAction); + } + + public static MasaDbContextOptionsBuilder UseMySQL( + this MasaDbContextOptionsBuilder builder, + string connectionString, + Action? mySQLOptionsAction = null) + { + builder.DbContextOptionsBuilder.UseMySQL(connectionString, mySQLOptionsAction); + return builder; + } +} diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.MySql/README.md b/src/Data/Masa.Utils.Data.EntityFrameworkCore.MySql/README.md new file mode 100644 index 0000000..06c736a --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.MySql/README.md @@ -0,0 +1,33 @@ +[中](README.zh-CN.md) | EN + +## Masa.Utils.Data.EntityFrameworkCore.MySql + +## Example: + +```c# +Install-Package Masa.Utils.Data.EntityFrameworkCore.MySql +``` + +##### Usage 1: + +1. Configure appsettings.json + +``` appsettings.json +{ + "ConnectionStrings": { + "DefaultConnection": "Server=localhost;Database=identity;Uid=myUsername;Pwd=P@ssw0rd;" + } +} +``` + +2. Using MasaDbContext + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseMySQL()); +``` + +##### Usage 2: + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseMySQL("Server=localhost;Database=identity;Uid=myUsername;Pwd=P@ssw0rd;")); +``` \ No newline at end of file diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.MySql/README.zh-CN.md b/src/Data/Masa.Utils.Data.EntityFrameworkCore.MySql/README.zh-CN.md new file mode 100644 index 0000000..556a80b --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.MySql/README.zh-CN.md @@ -0,0 +1,33 @@ +中 | [EN](README.md) + +## Masa.Utils.Data.EntityFrameworkCore.MySql + +## 用例: + +```c# +Install-Package Masa.Utils.Data.EntityFrameworkCore.MySql +``` + +#### 用法1: + +1. 配置appsettings.json + +``` appsettings.json +{ + "ConnectionStrings": { + "DefaultConnection": "Server=localhost;Database=identity;Uid=myUsername;Pwd=P@ssw0rd;" + } +} +``` + +2. 使用MasaDbContext + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseMySQL()); +``` + +#### 用法2: + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseMySQL("Server=localhost;Database=identity;Uid=myUsername;Pwd=P@ssw0rd;")); +``` \ No newline at end of file diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.MySql/_Imports.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore.MySql/_Imports.cs new file mode 100644 index 0000000..21acd93 --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.MySql/_Imports.cs @@ -0,0 +1,3 @@ +global using Microsoft.EntityFrameworkCore; +global using Microsoft.Extensions.DependencyInjection; +global using MySql.EntityFrameworkCore.Infrastructure; From 3e9a23feeb4984fb7bbd9e65f4ed7d6d1ff936f3 Mon Sep 17 00:00:00 2001 From: zhenlei520 Date: Thu, 17 Mar 2022 23:44:39 +0800 Subject: [PATCH 12/24] feat(EntityFrameworkCore.Oracle): support EntityFrameworkCore.Oracle --- ...ils.Data.EntityFrameworkCore.Oracle.csproj | 17 ++++++++++ .../MasaDbContextOptionsBuilderExtensions.cs | 21 ++++++++++++ .../README.md | 33 +++++++++++++++++++ .../README.zh-CN.md | 33 +++++++++++++++++++ .../_Imports.cs | 3 ++ 5 files changed, 107 insertions(+) create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.Oracle/Masa.Utils.Data.EntityFrameworkCore.Oracle.csproj create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.Oracle/MasaDbContextOptionsBuilderExtensions.cs create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.Oracle/README.md create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.Oracle/README.zh-CN.md create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.Oracle/_Imports.cs diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.Oracle/Masa.Utils.Data.EntityFrameworkCore.Oracle.csproj b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Oracle/Masa.Utils.Data.EntityFrameworkCore.Oracle.csproj new file mode 100644 index 0000000..83b530d --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Oracle/Masa.Utils.Data.EntityFrameworkCore.Oracle.csproj @@ -0,0 +1,17 @@ + + + + net6.0 + enable + enable + + + + + + + + + + + diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.Oracle/MasaDbContextOptionsBuilderExtensions.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Oracle/MasaDbContextOptionsBuilderExtensions.cs new file mode 100644 index 0000000..74d946f --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Oracle/MasaDbContextOptionsBuilderExtensions.cs @@ -0,0 +1,21 @@ +namespace Masa.Utils.Data.EntityFrameworkCore.Oracle; + +public static class MasaDbContextOptionsBuilderExtensions +{ + public static MasaDbContextOptionsBuilder UseOracle( + this MasaDbContextOptionsBuilder builder, + Action? oracleOptionsAction = null) + { + var connectionStringProvider = builder.ServiceProvider.GetRequiredService(); + return builder.UseOracle(connectionStringProvider.GetConnectionString(), oracleOptionsAction); + } + + public static MasaDbContextOptionsBuilder UseOracle( + this MasaDbContextOptionsBuilder builder, + string connectionString, + Action? oracleOptionsAction = null) + { + builder.DbContextOptionsBuilder.UseOracle(connectionString, oracleOptionsAction); + return builder; + } +} diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.Oracle/README.md b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Oracle/README.md new file mode 100644 index 0000000..d7bc88e --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Oracle/README.md @@ -0,0 +1,33 @@ +[中](README.zh-CN.md) | EN + +## Masa.Utils.Data.EntityFrameworkCore.Oracle + +## Example: + +```c# +Install-Package Masa.Utils.Data.EntityFrameworkCore.Oracle +``` + +##### Usage 1: + +1. Configure appsettings.json + +``` appsettings.json +{ + "ConnectionStrings": { + "DefaultConnection": "Data Source=MyOracleDB;Integrated Security=yes;" + } +} +``` + +2. Using MasaDbContext + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseOracle()); +``` + +##### Usage 2: + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseOracle("Data Source=MyOracleDB;Integrated Security=yes;")); +``` \ No newline at end of file diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.Oracle/README.zh-CN.md b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Oracle/README.zh-CN.md new file mode 100644 index 0000000..0e403a7 --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Oracle/README.zh-CN.md @@ -0,0 +1,33 @@ +中 | [EN](README.md) + +## Masa.Utils.Data.EntityFrameworkCore.Oracle + +## 用例: + +```c# +Install-Package Masa.Utils.Data.EntityFrameworkCore.Oracle +``` + +#### 用法1: + +1. 配置appsettings.json + +``` appsettings.json +{ + "ConnectionStrings": { + "DefaultConnection": "Data Source=MyOracleDB;Integrated Security=yes;" + } +} +``` + +2. 使用MasaDbContext + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseOracle()); +``` + +#### 用法2: + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseOracle("Data Source=MyOracleDB;Integrated Security=yes;")); +``` \ No newline at end of file diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.Oracle/_Imports.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Oracle/_Imports.cs new file mode 100644 index 0000000..8acf1f5 --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Oracle/_Imports.cs @@ -0,0 +1,3 @@ +global using Microsoft.EntityFrameworkCore; +global using Microsoft.Extensions.DependencyInjection; +global using Oracle.EntityFrameworkCore.Infrastructure; From 4bb6845d80b5c10e08ff0cbbbb2568e58a89d38b Mon Sep 17 00:00:00 2001 From: zhenlei520 Date: Thu, 17 Mar 2022 23:45:05 +0800 Subject: [PATCH 13/24] feat(EntityFrameworkCore.PostgreSql): support EntityFrameworkCore.PostgreSql --- ...Data.EntityFrameworkCore.PostgreSql.csproj | 17 ++++++++++ .../MasaDbContextOptionsBuilderExtensions.cs | 21 ++++++++++++ .../README.md | 33 +++++++++++++++++++ .../README.zh-CN.md | 33 +++++++++++++++++++ .../_Imports.cs | 3 ++ 5 files changed, 107 insertions(+) create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.PostgreSql/Masa.Utils.Data.EntityFrameworkCore.PostgreSql.csproj create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.PostgreSql/MasaDbContextOptionsBuilderExtensions.cs create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.PostgreSql/README.md create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.PostgreSql/README.zh-CN.md create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.PostgreSql/_Imports.cs diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.PostgreSql/Masa.Utils.Data.EntityFrameworkCore.PostgreSql.csproj b/src/Data/Masa.Utils.Data.EntityFrameworkCore.PostgreSql/Masa.Utils.Data.EntityFrameworkCore.PostgreSql.csproj new file mode 100644 index 0000000..c15c9df --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.PostgreSql/Masa.Utils.Data.EntityFrameworkCore.PostgreSql.csproj @@ -0,0 +1,17 @@ + + + + net6.0 + enable + enable + + + + + + + + + + + diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.PostgreSql/MasaDbContextOptionsBuilderExtensions.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore.PostgreSql/MasaDbContextOptionsBuilderExtensions.cs new file mode 100644 index 0000000..4ec9326 --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.PostgreSql/MasaDbContextOptionsBuilderExtensions.cs @@ -0,0 +1,21 @@ +namespace Masa.Utils.Data.EntityFrameworkCore.PostgreSql; + +public static class MasaDbContextOptionsBuilderExtensions +{ + public static MasaDbContextOptionsBuilder UseNpgsql( + this MasaDbContextOptionsBuilder builder, + Action? npgsqlOptionsAction = null) + { + var connectionStringProvider = builder.ServiceProvider.GetRequiredService(); + return builder.UseNpgsql(connectionStringProvider.GetConnectionString(), npgsqlOptionsAction); + } + + public static MasaDbContextOptionsBuilder UseNpgsql( + this MasaDbContextOptionsBuilder builder, + string connectionString, + Action? npgsqlOptionsAction = null) + { + builder.DbContextOptionsBuilder.UseNpgsql(connectionString, npgsqlOptionsAction); + return builder; + } +} diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.PostgreSql/README.md b/src/Data/Masa.Utils.Data.EntityFrameworkCore.PostgreSql/README.md new file mode 100644 index 0000000..8a4b147 --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.PostgreSql/README.md @@ -0,0 +1,33 @@ +[中](README.zh-CN.md) | EN + +## Masa.Utils.Data.EntityFrameworkCore.PostgreSql + +## Example: + +```c# +Install-Package Masa.Utils.Data.EntityFrameworkCore.PostgreSql +``` + +##### Usage 1: + +1. Configure appsettings.json + +``` appsettings.json +{ + "ConnectionStrings": { + "DefaultConnection": "Host=myserver;Username=sa;Password=P@ssw0rd;Database=identity" + } +} +``` + +2. Using MasaDbContext + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseNpgsql()); +``` + +##### Usage 2: + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseNpgsql("Host=myserver;Username=sa;Password=P@ssw0rd;Database=identity")); +``` \ No newline at end of file diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.PostgreSql/README.zh-CN.md b/src/Data/Masa.Utils.Data.EntityFrameworkCore.PostgreSql/README.zh-CN.md new file mode 100644 index 0000000..e80db90 --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.PostgreSql/README.zh-CN.md @@ -0,0 +1,33 @@ +中 | [EN](README.md) + +## Masa.Utils.Data.EntityFrameworkCore.PostgreSql + +## 用例: + +```c# +Install-Package Masa.Utils.Data.EntityFrameworkCore.PostgreSql +``` + +#### 用法1: + +1. 配置appsettings.json + +``` appsettings.json +{ + "ConnectionStrings": { + "DefaultConnection": "Host=myserver;Username=sa;Password=P@ssw0rd;Database=identity" + } +} +``` + +2. 使用MasaDbContext + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseNpgsql()); +``` + +#### 用法2: + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseNpgsql("Host=myserver;Username=sa;Password=P@ssw0rd;Database=identity")); +``` \ No newline at end of file diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.PostgreSql/_Imports.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore.PostgreSql/_Imports.cs new file mode 100644 index 0000000..35b7797 --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.PostgreSql/_Imports.cs @@ -0,0 +1,3 @@ +global using Microsoft.EntityFrameworkCore; +global using Microsoft.Extensions.DependencyInjection; +global using Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure; From b94bc1b8da382f11aa54f0f4ad2dc7750195b8a7 Mon Sep 17 00:00:00 2001 From: zhenlei520 Date: Thu, 17 Mar 2022 23:45:30 +0800 Subject: [PATCH 14/24] feat(EntityFrameworkCore.Sqlite): support EntityFrameworkCore.Sqlite --- ...ils.Data.EntityFrameworkCore.Sqlite.csproj | 17 ++++++++++ .../MasaDbContextOptionsBuilderExtensions.cs | 21 ++++++++++++ .../README.md | 33 +++++++++++++++++++ .../README.zh-CN.md | 33 +++++++++++++++++++ .../_Imports.cs | 3 ++ 5 files changed, 107 insertions(+) create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.Sqlite/Masa.Utils.Data.EntityFrameworkCore.Sqlite.csproj create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.Sqlite/MasaDbContextOptionsBuilderExtensions.cs create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.Sqlite/README.md create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.Sqlite/README.zh-CN.md create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.Sqlite/_Imports.cs diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.Sqlite/Masa.Utils.Data.EntityFrameworkCore.Sqlite.csproj b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Sqlite/Masa.Utils.Data.EntityFrameworkCore.Sqlite.csproj new file mode 100644 index 0000000..f79694e --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Sqlite/Masa.Utils.Data.EntityFrameworkCore.Sqlite.csproj @@ -0,0 +1,17 @@ + + + + net6.0 + enable + enable + + + + + + + + + + + diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.Sqlite/MasaDbContextOptionsBuilderExtensions.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Sqlite/MasaDbContextOptionsBuilderExtensions.cs new file mode 100644 index 0000000..7b57519 --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Sqlite/MasaDbContextOptionsBuilderExtensions.cs @@ -0,0 +1,21 @@ +namespace Masa.Utils.Data.EntityFrameworkCore.Sqlite; + +public static class MasaDbContextOptionsBuilderExtensions +{ + public static MasaDbContextOptionsBuilder UseSqlite( + this MasaDbContextOptionsBuilder builder, + Action? sqliteOptionsAction = null) + { + var connectionStringProvider = builder.ServiceProvider.GetRequiredService(); + return builder.UseSqlite(connectionStringProvider.GetConnectionString(), sqliteOptionsAction); + } + + public static MasaDbContextOptionsBuilder UseSqlite( + this MasaDbContextOptionsBuilder builder, + string connectionString, + Action? sqliteOptionsAction = null) + { + builder.DbContextOptionsBuilder.UseSqlite(connectionString, sqliteOptionsAction); + return builder; + } +} diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.Sqlite/README.md b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Sqlite/README.md new file mode 100644 index 0000000..e9632e0 --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Sqlite/README.md @@ -0,0 +1,33 @@ +[中](README.zh-CN.md) | EN + +## Masa.Utils.Data.EntityFrameworkCore.Sqlite + +## Example: + +```c# +Install-Package Masa.Utils.Data.EntityFrameworkCore.Sqlite +``` + +##### Usage 1: + +1. Configure appsettings.json + +``` appsettings.json +{ + "ConnectionStrings": { + "DefaultConnection": "Data Source=c:\mydb.db;Version=3;Password=P@ssw0rd;" + } +} +``` + +2. Using MasaDbContext + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseSqlite()); +``` + +##### Usage 2: + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseSqlite("Data Source=c:\mydb.db;Version=3;Password=P@ssw0rd;")); +``` \ No newline at end of file diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.Sqlite/README.zh-CN.md b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Sqlite/README.zh-CN.md new file mode 100644 index 0000000..d1dbc6d --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Sqlite/README.zh-CN.md @@ -0,0 +1,33 @@ +中 | [EN](README.md) + +## Masa.Utils.Data.EntityFrameworkCore.Sqlite + +## 用例: + +```c# +Install-Package Masa.Utils.Data.EntityFrameworkCore.Sqlite +``` + +#### 用法1: + +1. 配置appsettings.json + +``` appsettings.json +{ + "ConnectionStrings": { + "DefaultConnection": "Data Source=c:\mydb.db;Version=3;Password=P@ssw0rd;" + } +} +``` + +2. 使用MasaDbContext + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseSqlite()); +``` + +#### 用法2: + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseSqlite("Data Source=c:\mydb.db;Version=3;Password=P@ssw0rd;")); +``` \ No newline at end of file diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.Sqlite/_Imports.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Sqlite/_Imports.cs new file mode 100644 index 0000000..c0cb4f2 --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Sqlite/_Imports.cs @@ -0,0 +1,3 @@ +global using Microsoft.EntityFrameworkCore; +global using Microsoft.EntityFrameworkCore.Infrastructure; +global using Microsoft.Extensions.DependencyInjection; From 4b331d12c5be42ba2c247c82da44c9864ccf7d92 Mon Sep 17 00:00:00 2001 From: zhenlei520 Date: Thu, 17 Mar 2022 23:54:09 +0800 Subject: [PATCH 15/24] chore(EntityFrameworkCore.MySql): change parameter name --- .../MasaDbContextOptionsBuilderExtensions.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.MySql/MasaDbContextOptionsBuilderExtensions.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore.MySql/MasaDbContextOptionsBuilderExtensions.cs index 028dab2..2e72ddd 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore.MySql/MasaDbContextOptionsBuilderExtensions.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.MySql/MasaDbContextOptionsBuilderExtensions.cs @@ -4,18 +4,18 @@ public static class MasaDbContextOptionsBuilderExtensions { public static MasaDbContextOptionsBuilder UseMySQL( this MasaDbContextOptionsBuilder builder, - Action? mySQLOptionsAction = null) + Action? mySqlOptionsAction = null) { var connectionStringProvider = builder.ServiceProvider.GetRequiredService(); - return builder.UseMySQL(connectionStringProvider.GetConnectionString(), mySQLOptionsAction); + return builder.UseMySQL(connectionStringProvider.GetConnectionString(), mySqlOptionsAction); } public static MasaDbContextOptionsBuilder UseMySQL( this MasaDbContextOptionsBuilder builder, string connectionString, - Action? mySQLOptionsAction = null) + Action? mySqlOptionsAction = null) { - builder.DbContextOptionsBuilder.UseMySQL(connectionString, mySQLOptionsAction); + builder.DbContextOptionsBuilder.UseMySQL(connectionString, mySqlOptionsAction); return builder; } } From 455253ea7b9f4b2790c185e4a8c8aa10d2b3f631 Mon Sep 17 00:00:00 2001 From: zhenlei520 Date: Thu, 17 Mar 2022 23:54:41 +0800 Subject: [PATCH 16/24] feat(EntityFrameworkCore.Pomelo.MySql): support mysql by Pomelo.EntityFrameworkCore.MySql --- ...ta.EntityFrameworkCore.Pomelo.MySql.csproj | 17 ++++++++++ .../MasaDbContextOptionsBuilderExtensions.cs | 23 +++++++++++++ .../README.md | 33 +++++++++++++++++++ .../README.zh-CN.md | 33 +++++++++++++++++++ .../_Imports.cs | 3 ++ 5 files changed, 109 insertions(+) create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql/Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql.csproj create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql/MasaDbContextOptionsBuilderExtensions.cs create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql/README.md create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql/README.zh-CN.md create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql/_Imports.cs diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql/Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql.csproj b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql/Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql.csproj new file mode 100644 index 0000000..f62b3f4 --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql/Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql.csproj @@ -0,0 +1,17 @@ + + + + net6.0 + enable + enable + + + + + + + + + + + diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql/MasaDbContextOptionsBuilderExtensions.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql/MasaDbContextOptionsBuilderExtensions.cs new file mode 100644 index 0000000..a2b86ba --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql/MasaDbContextOptionsBuilderExtensions.cs @@ -0,0 +1,23 @@ +namespace Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql; + +public static class MasaDbContextOptionsBuilderExtensions +{ + public static MasaDbContextOptionsBuilder UseMySql( + this MasaDbContextOptionsBuilder builder, + ServerVersion serverVersion, + Action? mySqlOptionsAction = null) + { + var connectionStringProvider = builder.ServiceProvider.GetRequiredService(); + return builder.UseMySql(connectionStringProvider.GetConnectionString(), serverVersion, mySqlOptionsAction); + } + + public static MasaDbContextOptionsBuilder UseMySql( + this MasaDbContextOptionsBuilder builder, + string connectionString, + ServerVersion serverVersion, + Action? mySqlOptionsAction = null) + { + builder.DbContextOptionsBuilder.UseMySql(connectionString, serverVersion, mySqlOptionsAction); + return builder; + } +} diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql/README.md b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql/README.md new file mode 100644 index 0000000..7543af5 --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql/README.md @@ -0,0 +1,33 @@ +[中](README.zh-CN.md) | EN + +## Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql + +## Example: + +```c# +Install-Package Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql +``` + +##### Usage 1: + +1. Configure appsettings.json + +``` appsettings.json +{ + "ConnectionStrings": { + "DefaultConnection": "Server=localhost;Database=identity;Uid=myUsername;Pwd=P@ssw0rd;" + } +} +``` + +2. Using MasaDbContext + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseMySql(Microsoft.EntityFrameworkCore.ServerVersion.Parse("5.7.28-mysql"))); +``` + +##### Usage 2: + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseMySql("Server=localhost;Database=identity;Uid=myUsername;Pwd=P@ssw0rd;", Microsoft.EntityFrameworkCore.ServerVersion.Parse("5.7.28-mysql"))); +``` \ No newline at end of file diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql/README.zh-CN.md b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql/README.zh-CN.md new file mode 100644 index 0000000..d926c24 --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql/README.zh-CN.md @@ -0,0 +1,33 @@ +中 | [EN](README.md) + +## Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql + +## 用例: + +```c# +Install-Package Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql +``` + +#### 用法1: + +1. 配置appsettings.json + +``` appsettings.json +{ + "ConnectionStrings": { + "DefaultConnection": "Server=localhost;Database=identity;Uid=myUsername;Pwd=P@ssw0rd;" + } +} +``` + +2. 使用MasaDbContext + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseMySql(Microsoft.EntityFrameworkCore.ServerVersion.Parse("5.7.28-mysql"))); +``` + +#### 用法2: + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseMySql("Server=localhost;Database=identity;Uid=myUsername;Pwd=P@ssw0rd;", Microsoft.EntityFrameworkCore.ServerVersion.Parse("5.7.28-mysql"))); +``` \ No newline at end of file diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql/_Imports.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql/_Imports.cs new file mode 100644 index 0000000..c0cb4f2 --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql/_Imports.cs @@ -0,0 +1,3 @@ +global using Microsoft.EntityFrameworkCore; +global using Microsoft.EntityFrameworkCore.Infrastructure; +global using Microsoft.Extensions.DependencyInjection; From c4109491dbef655cd85890b32601ac405882aed9 Mon Sep 17 00:00:00 2001 From: zhenlei520 Date: Fri, 18 Mar 2022 00:38:06 +0800 Subject: [PATCH 17/24] chore(caller.test): change file encoding --- test/Masa.Utils.Caller.Core.Tests/CallerTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Masa.Utils.Caller.Core.Tests/CallerTest.cs b/test/Masa.Utils.Caller.Core.Tests/CallerTest.cs index b83dfe9..4abf8c0 100644 --- a/test/Masa.Utils.Caller.Core.Tests/CallerTest.cs +++ b/test/Masa.Utils.Caller.Core.Tests/CallerTest.cs @@ -1,4 +1,4 @@ -namespace Masa.Utils.Caller.Core.Tests; +namespace Masa.Utils.Caller.Core.Tests; [TestClass] public class CallerTest From 35155334b28098b44697d9c757106c829c69b6f3 Mon Sep 17 00:00:00 2001 From: zhenlei520 Date: Fri, 18 Mar 2022 00:39:00 +0800 Subject: [PATCH 18/24] feat(EntityFrameworkCore.Cosmos): support EntityFrameworkCore.Cosmos --- ...ils.Data.EntityFrameworkCore.Cosmos.csproj | 17 +++++++ .../MasaDbContextOptionsBuilderExtensions.cs | 45 +++++++++++++++++++ .../README.md | 34 ++++++++++++++ .../README.zh-CN.md | 34 ++++++++++++++ .../_Imports.cs | 4 ++ 5 files changed, 134 insertions(+) create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.Cosmos/Masa.Utils.Data.EntityFrameworkCore.Cosmos.csproj create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.Cosmos/MasaDbContextOptionsBuilderExtensions.cs create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.Cosmos/README.md create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.Cosmos/README.zh-CN.md create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.Cosmos/_Imports.cs diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.Cosmos/Masa.Utils.Data.EntityFrameworkCore.Cosmos.csproj b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Cosmos/Masa.Utils.Data.EntityFrameworkCore.Cosmos.csproj new file mode 100644 index 0000000..e235b25 --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Cosmos/Masa.Utils.Data.EntityFrameworkCore.Cosmos.csproj @@ -0,0 +1,17 @@ + + + + net6.0 + enable + enable + + + + + + + + + + + diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.Cosmos/MasaDbContextOptionsBuilderExtensions.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Cosmos/MasaDbContextOptionsBuilderExtensions.cs new file mode 100644 index 0000000..17b24c2 --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Cosmos/MasaDbContextOptionsBuilderExtensions.cs @@ -0,0 +1,45 @@ +namespace Masa.Utils.Data.EntityFrameworkCore.Cosmos; + +public static class MasaDbContextOptionsBuilderExtensions +{ + public static MasaDbContextOptionsBuilder UseCosmos( + this MasaDbContextOptionsBuilder builder, + Action? cosmosOptionsAction = null) + { + var connectionStringProvider = builder.ServiceProvider.GetRequiredService(); + var configurationDic = connectionStringProvider.GetConnectionString().ToDictionary(); + + if (!configurationDic.TryGetValue("Database", out string? databaseName)) + throw new ArgumentException("Cosmos: Bad database connection string, Failed to get [Database] name"); + + if (configurationDic.TryGetValue("ConnectionString", out string? connectionString)) + return builder.UseCosmos(connectionString, databaseName, cosmosOptionsAction); + + if (!configurationDic.TryGetValue("AccountKey", out string? accountKey) || + !configurationDic.TryGetValue("AccountEndpoint", out string? accountEndpoint)) + throw new ArgumentException("Cosmos: Bad database connection string, Failed to get [AccountKey] name or [AccountEndpoint] name"); + + return builder.UseCosmos(accountEndpoint, accountKey, databaseName, cosmosOptionsAction); + } + + public static MasaDbContextOptionsBuilder UseCosmos( + this MasaDbContextOptionsBuilder builder, + string accountEndpoint, + string accountKey, + string databaseName, + Action? cosmosOptionsAction = null) + { + builder.DbContextOptionsBuilder.UseCosmos(accountEndpoint, accountKey, databaseName, cosmosOptionsAction); + return builder; + } + + public static MasaDbContextOptionsBuilder UseCosmos( + this MasaDbContextOptionsBuilder builder, + string connectionString, + string databaseName, + Action? cosmosOptionsAction = null) + { + builder.DbContextOptionsBuilder.UseCosmos(connectionString, databaseName, cosmosOptionsAction); + return builder; + } +} diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.Cosmos/README.md b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Cosmos/README.md new file mode 100644 index 0000000..6689145 --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Cosmos/README.md @@ -0,0 +1,34 @@ +[中](README.zh-CN.md) | EN + +## Masa.Utils.Data.EntityFrameworkCore.Cosmos + +## Example: + +```c# +Install-Package Masa.Utils.Data.EntityFrameworkCore.Cosmos +``` + +##### Usage 1: + +1. Configure appsettings.json + +``` appsettings.json +{ + "ConnectionStrings": { + "DefaultConnection": "AccountKey=AccountKey;AccountEndpoint=AccountEndpoint;Database=Database"//或"ConnectionString=ConnectionString;Database=Database" + } +} +``` + +2. Using MasaDbContext + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseCosmos()); +``` + +##### Usage 2: + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseCosmos($"{accountEndpoint}",$"{accountKey}",$"{databaseName}")); +//builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseCosmos($"{connectionString}",$"{databaseName}")); +``` \ No newline at end of file diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.Cosmos/README.zh-CN.md b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Cosmos/README.zh-CN.md new file mode 100644 index 0000000..74b41c2 --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Cosmos/README.zh-CN.md @@ -0,0 +1,34 @@ +中 | [EN](README.md) + +## Masa.Utils.Data.EntityFrameworkCore.Cosmos + +## 用例: + +```c# +Install-Package Masa.Utils.Data.EntityFrameworkCore.Cosmos +``` + +#### 用法1: + +1. 配置appsettings.json + +``` appsettings.json +{ + "ConnectionStrings": { + "DefaultConnection": "AccountKey=AccountKey;AccountEndpoint=AccountEndpoint;Database=Database"//或"ConnectionString=ConnectionString;Database=Database" + } +} +``` + +2. 使用MasaDbContext + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseCosmos()); +``` + +#### 用法2: + +``` C# +builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseCosmos($"{accountEndpoint}",$"{accountKey}",$"{databaseName}")); +//builder.Services.AddMasaDbContext(optionsBuilder => optionsBuilder.UseSoftDelete().UseCosmos($"{connectionString}",$"{databaseName}")); +``` \ No newline at end of file diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.Cosmos/_Imports.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Cosmos/_Imports.cs new file mode 100644 index 0000000..3f8ac7f --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Cosmos/_Imports.cs @@ -0,0 +1,4 @@ +global using Microsoft.EntityFrameworkCore; +global using Microsoft.EntityFrameworkCore.Infrastructure; +global using Microsoft.Extensions.DependencyInjection; +global using Masa.Utils.Data.EntityFrameworkCore.Cosmos.Internal; From 1ad3dca7779c15afe9a56a1a29886c5914e4eef4 Mon Sep 17 00:00:00 2001 From: zhenlei520 Date: Fri, 18 Mar 2022 00:44:33 +0800 Subject: [PATCH 19/24] docs(EntityFrameworkCore): Improve EntityFramework documentation --- Masa.Utils.sln | 105 +++++++++++++----- .../Internal/Parser.cs | 23 ++++ .../README.md | 9 +- .../README.zh-CN.md | 11 +- 4 files changed, 117 insertions(+), 31 deletions(-) create mode 100644 src/Data/Masa.Utils.Data.EntityFrameworkCore.Cosmos/Internal/Parser.cs diff --git a/Masa.Utils.sln b/Masa.Utils.sln index efe3eed..c697fd3 100644 --- a/Masa.Utils.sln +++ b/Masa.Utils.sln @@ -29,61 +29,75 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Security", "Security", "{4F EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Development", "Development", "{598A7DA7-898E-429B-992A-B0E586DADA35}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Caching.Core", "src\Caching\Masa.Utils.Caching.Core\Masa.Utils.Caching.Core.csproj", "{91A68564-07EA-439D-BED3-EFC068A159D0}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Utils.Caching.Core", "src\Caching\Masa.Utils.Caching.Core\Masa.Utils.Caching.Core.csproj", "{91A68564-07EA-439D-BED3-EFC068A159D0}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Caching.DistributedMemory", "src\Caching\Masa.Utils.Caching.DistributedMemory\Masa.Utils.Caching.DistributedMemory.csproj", "{9E3EE563-9DB0-4DCE-A844-CEFC5C7D1D56}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Utils.Caching.DistributedMemory", "src\Caching\Masa.Utils.Caching.DistributedMemory\Masa.Utils.Caching.DistributedMemory.csproj", "{9E3EE563-9DB0-4DCE-A844-CEFC5C7D1D56}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Caching.Memory", "src\Caching\Masa.Utils.Caching.Memory\Masa.Utils.Caching.Memory.csproj", "{F75C5658-C7EB-4922-833F-9052D9723487}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Utils.Caching.Memory", "src\Caching\Masa.Utils.Caching.Memory\Masa.Utils.Caching.Memory.csproj", "{F75C5658-C7EB-4922-833F-9052D9723487}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Caching.Redis", "src\Caching\Masa.Utils.Caching.Redis\Masa.Utils.Caching.Redis.csproj", "{246AA228-57AC-40B4-9BE1-EC75B8C3FC10}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Utils.Caching.Redis", "src\Caching\Masa.Utils.Caching.Redis\Masa.Utils.Caching.Redis.csproj", "{246AA228-57AC-40B4-9BE1-EC75B8C3FC10}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Caller.Core", "src\Caller\Masa.Utils.Caller.Core\Masa.Utils.Caller.Core.csproj", "{AE2109F8-6772-41A8-88C3-8E603BA29144}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Utils.Caller.Core", "src\Caller\Masa.Utils.Caller.Core\Masa.Utils.Caller.Core.csproj", "{AE2109F8-6772-41A8-88C3-8E603BA29144}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Caller.DaprClient", "src\Caller\Masa.Utils.Caller.DaprClient\Masa.Utils.Caller.DaprClient.csproj", "{A489F659-7925-475E-A82E-EFEE846C24C8}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Utils.Caller.DaprClient", "src\Caller\Masa.Utils.Caller.DaprClient\Masa.Utils.Caller.DaprClient.csproj", "{A489F659-7925-475E-A82E-EFEE846C24C8}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Caller.HttpClient", "src\Caller\Masa.Utils.Caller.HttpClient\Masa.Utils.Caller.HttpClient.csproj", "{ACE02BC6-04E9-48F5-BF1A-C5591366F72A}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Utils.Caller.HttpClient", "src\Caller\Masa.Utils.Caller.HttpClient\Masa.Utils.Caller.HttpClient.csproj", "{ACE02BC6-04E9-48F5-BF1A-C5591366F72A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Configuration.Dcc", "src\Configuration\Masa.Utils.Configuration.Dcc\Masa.Utils.Configuration.Dcc.csproj", "{31A832FC-2AC6-4540-A659-1DCFF7882102}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Utils.Configuration.Dcc", "src\Configuration\Masa.Utils.Configuration.Dcc\Masa.Utils.Configuration.Dcc.csproj", "{31A832FC-2AC6-4540-A659-1DCFF7882102}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Configuration.Json", "src\Configuration\Masa.Utils.Configuration.Json\Masa.Utils.Configuration.Json.csproj", "{4C9A3FE2-7958-4DEE-A478-7DE5B99A77C4}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Utils.Configuration.Json", "src\Configuration\Masa.Utils.Configuration.Json\Masa.Utils.Configuration.Json.csproj", "{4C9A3FE2-7958-4DEE-A478-7DE5B99A77C4}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Data.DataAnnotations", "src\Data\Masa.Utils.Data.DataAnnotations\Masa.Utils.Data.DataAnnotations.csproj", "{AAC6E291-48D8-41AD-99C0-5B085EB88F81}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Utils.Data.DataAnnotations", "src\Data\Masa.Utils.Data.DataAnnotations\Masa.Utils.Data.DataAnnotations.csproj", "{AAC6E291-48D8-41AD-99C0-5B085EB88F81}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Data.Elasticsearch", "src\Data\Masa.Utils.Data.Elasticsearch\Masa.Utils.Data.Elasticsearch.csproj", "{306184FE-65BE-4763-A86E-D84BBB8CFDDF}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Utils.Data.Elasticsearch", "src\Data\Masa.Utils.Data.Elasticsearch\Masa.Utils.Data.Elasticsearch.csproj", "{306184FE-65BE-4763-A86E-D84BBB8CFDDF}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Data.EntityFrameworkCore", "src\Data\Masa.Utils.Data.EntityFrameworkCore\Masa.Utils.Data.EntityFrameworkCore.csproj", "{31DEB65E-ADE1-4B00-AE99-3ECBEF53D0C5}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Utils.Data.EntityFrameworkCore", "src\Data\Masa.Utils.Data.EntityFrameworkCore\Masa.Utils.Data.EntityFrameworkCore.csproj", "{31DEB65E-ADE1-4B00-AE99-3ECBEF53D0C5}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Development.Dapr", "src\Development\Masa.Utils.Development.Dapr\Masa.Utils.Development.Dapr.csproj", "{14FDF393-49F1-4D41-9EC0-FF493BDDE376}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Utils.Development.Dapr", "src\Development\Masa.Utils.Development.Dapr\Masa.Utils.Development.Dapr.csproj", "{14FDF393-49F1-4D41-9EC0-FF493BDDE376}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Development.Dapr.AspNetCore", "src\Development\Masa.Utils.Development.Dapr.AspNetCore\Masa.Utils.Development.Dapr.AspNetCore.csproj", "{BA28042B-25C1-4361-A836-5710BF271EEF}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Utils.Development.Dapr.AspNetCore", "src\Development\Masa.Utils.Development.Dapr.AspNetCore\Masa.Utils.Development.Dapr.AspNetCore.csproj", "{BA28042B-25C1-4361-A836-5710BF271EEF}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Enums", "src\Extensions\Masa.Utils.Enums\Masa.Utils.Enums.csproj", "{56E7A4C7-5AF3-4DD1-A6AA-E713CA1C19D6}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Utils.Enums", "src\Extensions\Masa.Utils.Enums\Masa.Utils.Enums.csproj", "{56E7A4C7-5AF3-4DD1-A6AA-E713CA1C19D6}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Expressions", "src\Extensions\Masa.Utils.Expressions\Masa.Utils.Expressions.csproj", "{22FB9445-2337-43F7-AEFB-6E349619CBB1}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Utils.Expressions", "src\Extensions\Masa.Utils.Expressions\Masa.Utils.Expressions.csproj", "{22FB9445-2337-43F7-AEFB-6E349619CBB1}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Extensions.DependencyInjection", "src\Extensions\Masa.Utils.Extensions.DependencyInjection\Masa.Utils.Extensions.DependencyInjection.csproj", "{6CC1E189-9249-44BB-B0C9-E13D173E85CE}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Utils.Extensions.DependencyInjection", "src\Extensions\Masa.Utils.Extensions.DependencyInjection\Masa.Utils.Extensions.DependencyInjection.csproj", "{6CC1E189-9249-44BB-B0C9-E13D173E85CE}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Extensions.DotNet", "src\Extensions\Masa.Utils.Extensions.DotNet\Masa.Utils.Extensions.DotNet.csproj", "{3244CF56-A19C-4A5B-B479-79DA704BDBB2}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Utils.Extensions.DotNet", "src\Extensions\Masa.Utils.Extensions.DotNet\Masa.Utils.Extensions.DotNet.csproj", "{3244CF56-A19C-4A5B-B479-79DA704BDBB2}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Exceptions", "src\Masa.Utils.Exceptions\Masa.Utils.Exceptions.csproj", "{8D573300-4173-41CA-A4C8-BAA49A89B4F8}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Utils.Exceptions", "src\Masa.Utils.Exceptions\Masa.Utils.Exceptions.csproj", "{8D573300-4173-41CA-A4C8-BAA49A89B4F8}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Models.Config", "src\Models\Masa.Utils.Models.Config\Masa.Utils.Models.Config.csproj", "{333E1D7C-780F-4917-A823-8B369F1D278C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Utils.Models.Config", "src\Models\Masa.Utils.Models.Config\Masa.Utils.Models.Config.csproj", "{333E1D7C-780F-4917-A823-8B369F1D278C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Security.Authentication", "src\Security\Masa.Utils.Security.Authentication\Masa.Utils.Security.Authentication.csproj", "{83F7EFDA-EF08-4931-82FA-A1A0EEE162A9}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Utils.Security.Authentication", "src\Security\Masa.Utils.Security.Authentication\Masa.Utils.Security.Authentication.csproj", "{83F7EFDA-EF08-4931-82FA-A1A0EEE162A9}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Security.Cryptography", "src\Security\Masa.Utils.Security.Cryptography\Masa.Utils.Security.Cryptography.csproj", "{C9D66303-AE01-4D8C-A69E-82B620007EBD}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Utils.Security.Cryptography", "src\Security\Masa.Utils.Security.Cryptography\Masa.Utils.Security.Cryptography.csproj", "{C9D66303-AE01-4D8C-A69E-82B620007EBD}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Security.Token", "src\Security\Masa.Utils.Security.Token\Masa.Utils.Security.Token.csproj", "{4A3B1928-5014-4D81-BB83-FDCD0652D067}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Utils.Security.Token", "src\Security\Masa.Utils.Security.Token\Masa.Utils.Security.Token.csproj", "{4A3B1928-5014-4D81-BB83-FDCD0652D067}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Data.DataAnnotations.Tests", "test\Masa.Utils.Data.DataAnnotations.Tests\Masa.Utils.Data.DataAnnotations.Tests.csproj", "{52B3A8FE-A553-4D65-8660-447F120616AB}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Utils.Data.DataAnnotations.Tests", "test\Masa.Utils.Data.DataAnnotations.Tests\Masa.Utils.Data.DataAnnotations.Tests.csproj", "{52B3A8FE-A553-4D65-8660-447F120616AB}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Security.Cryptography.Tests", "test\Masa.Utils.Security.Cryptography.Tests\Masa.Utils.Security.Cryptography.Tests.csproj", "{1A8FBE3D-B004-4D25-8FE0-A3632A0FDE9E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Utils.Security.Cryptography.Tests", "test\Masa.Utils.Security.Cryptography.Tests\Masa.Utils.Security.Cryptography.Tests.csproj", "{1A8FBE3D-B004-4D25-8FE0-A3632A0FDE9E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Caller.Core.Tests", "test\Masa.Utils.Caller.Core.Tests\Masa.Utils.Caller.Core.Tests.csproj", "{4B351F95-5919-46A9-A02F-F4409C9EA79A}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Utils.Caller.Core.Tests", "test\Masa.Utils.Caller.Core.Tests\Masa.Utils.Caller.Core.Tests.csproj", "{4B351F95-5919-46A9-A02F-F4409C9EA79A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Caller.IntegratedTest", "test\Masa.Utils.Caller.IntegratedTest\Masa.Utils.Caller.IntegratedTest.csproj", "{D5E09920-081B-478C-B77B-EAB77931F47D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Utils.Caller.IntegratedTest", "test\Masa.Utils.Caller.IntegratedTest\Masa.Utils.Caller.IntegratedTest.csproj", "{D5E09920-081B-478C-B77B-EAB77931F47D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Data.EntityFrameworkCore.SqlServer", "src\Data\Masa.Utils.Data.EntityFrameworkCore.SqlServer\Masa.Utils.Data.EntityFrameworkCore.SqlServer.csproj", "{9004B687-3EB7-4156-A3F7-078A342F2BEF}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Utils.Data.EntityFrameworkCore.SqlServer", "src\Data\Masa.Utils.Data.EntityFrameworkCore.SqlServer\Masa.Utils.Data.EntityFrameworkCore.SqlServer.csproj", "{9004B687-3EB7-4156-A3F7-078A342F2BEF}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Utils.Data.EntityFrameworkCore.Sqlite", "src\Data\Masa.Utils.Data.EntityFrameworkCore.Sqlite\Masa.Utils.Data.EntityFrameworkCore.Sqlite.csproj", "{4C3C99D6-A832-4D14-B1C8-54B6E0780F24}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Utils.Data.EntityFrameworkCore.MySql", "src\Data\Masa.Utils.Data.EntityFrameworkCore.MySql\Masa.Utils.Data.EntityFrameworkCore.MySql.csproj", "{8AE29CEB-89D3-4AE3-8F97-D03D19F0B6FB}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Utils.Data.EntityFrameworkCore.InMemory", "src\Data\Masa.Utils.Data.EntityFrameworkCore.InMemory\Masa.Utils.Data.EntityFrameworkCore.InMemory.csproj", "{95A1CAC2-42F5-4916-99D2-64D9C830B1B3}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Utils.Data.EntityFrameworkCore.Oracle", "src\Data\Masa.Utils.Data.EntityFrameworkCore.Oracle\Masa.Utils.Data.EntityFrameworkCore.Oracle.csproj", "{6FFA2D43-D011-4E1B-B2DA-A6DF2816AA02}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.Utils.Data.EntityFrameworkCore.PostgreSql", "src\Data\Masa.Utils.Data.EntityFrameworkCore.PostgreSql\Masa.Utils.Data.EntityFrameworkCore.PostgreSql.csproj", "{D682F08B-6586-4C33-815D-8F98C50A0843}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql", "src\Data\Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql\Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql.csproj", "{2AB5DFD8-B537-4066-8366-E3F371BD5EE2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Data.EntityFrameworkCore.Cosmos", "src\Data\Masa.Utils.Data.EntityFrameworkCore.Cosmos\Masa.Utils.Data.EntityFrameworkCore.Cosmos.csproj", "{B8CB480B-2608-46A8-8528-37EDD5E1EC1E}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -203,6 +217,34 @@ Global {9004B687-3EB7-4156-A3F7-078A342F2BEF}.Debug|Any CPU.Build.0 = Debug|Any CPU {9004B687-3EB7-4156-A3F7-078A342F2BEF}.Release|Any CPU.ActiveCfg = Release|Any CPU {9004B687-3EB7-4156-A3F7-078A342F2BEF}.Release|Any CPU.Build.0 = Release|Any CPU + {4C3C99D6-A832-4D14-B1C8-54B6E0780F24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4C3C99D6-A832-4D14-B1C8-54B6E0780F24}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4C3C99D6-A832-4D14-B1C8-54B6E0780F24}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4C3C99D6-A832-4D14-B1C8-54B6E0780F24}.Release|Any CPU.Build.0 = Release|Any CPU + {8AE29CEB-89D3-4AE3-8F97-D03D19F0B6FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8AE29CEB-89D3-4AE3-8F97-D03D19F0B6FB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8AE29CEB-89D3-4AE3-8F97-D03D19F0B6FB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8AE29CEB-89D3-4AE3-8F97-D03D19F0B6FB}.Release|Any CPU.Build.0 = Release|Any CPU + {95A1CAC2-42F5-4916-99D2-64D9C830B1B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {95A1CAC2-42F5-4916-99D2-64D9C830B1B3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {95A1CAC2-42F5-4916-99D2-64D9C830B1B3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {95A1CAC2-42F5-4916-99D2-64D9C830B1B3}.Release|Any CPU.Build.0 = Release|Any CPU + {6FFA2D43-D011-4E1B-B2DA-A6DF2816AA02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6FFA2D43-D011-4E1B-B2DA-A6DF2816AA02}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6FFA2D43-D011-4E1B-B2DA-A6DF2816AA02}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6FFA2D43-D011-4E1B-B2DA-A6DF2816AA02}.Release|Any CPU.Build.0 = Release|Any CPU + {D682F08B-6586-4C33-815D-8F98C50A0843}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D682F08B-6586-4C33-815D-8F98C50A0843}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D682F08B-6586-4C33-815D-8F98C50A0843}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D682F08B-6586-4C33-815D-8F98C50A0843}.Release|Any CPU.Build.0 = Release|Any CPU + {2AB5DFD8-B537-4066-8366-E3F371BD5EE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2AB5DFD8-B537-4066-8366-E3F371BD5EE2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2AB5DFD8-B537-4066-8366-E3F371BD5EE2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2AB5DFD8-B537-4066-8366-E3F371BD5EE2}.Release|Any CPU.Build.0 = Release|Any CPU + {B8CB480B-2608-46A8-8528-37EDD5E1EC1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B8CB480B-2608-46A8-8528-37EDD5E1EC1E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B8CB480B-2608-46A8-8528-37EDD5E1EC1E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B8CB480B-2608-46A8-8528-37EDD5E1EC1E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -244,6 +286,13 @@ Global {4B351F95-5919-46A9-A02F-F4409C9EA79A} = {4F908878-0EB8-43E4-96E4-8B1F32E9B635} {D5E09920-081B-478C-B77B-EAB77931F47D} = {4F908878-0EB8-43E4-96E4-8B1F32E9B635} {9004B687-3EB7-4156-A3F7-078A342F2BEF} = {F844C2A1-C36D-400E-A0D8-7658EF9C3B93} + {4C3C99D6-A832-4D14-B1C8-54B6E0780F24} = {F844C2A1-C36D-400E-A0D8-7658EF9C3B93} + {8AE29CEB-89D3-4AE3-8F97-D03D19F0B6FB} = {F844C2A1-C36D-400E-A0D8-7658EF9C3B93} + {95A1CAC2-42F5-4916-99D2-64D9C830B1B3} = {F844C2A1-C36D-400E-A0D8-7658EF9C3B93} + {6FFA2D43-D011-4E1B-B2DA-A6DF2816AA02} = {F844C2A1-C36D-400E-A0D8-7658EF9C3B93} + {D682F08B-6586-4C33-815D-8F98C50A0843} = {F844C2A1-C36D-400E-A0D8-7658EF9C3B93} + {2AB5DFD8-B537-4066-8366-E3F371BD5EE2} = {F844C2A1-C36D-400E-A0D8-7658EF9C3B93} + {B8CB480B-2608-46A8-8528-37EDD5E1EC1E} = {F844C2A1-C36D-400E-A0D8-7658EF9C3B93} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {D7DAA0E6-098F-4B18-8775-64FDA96F1FF0} diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.Cosmos/Internal/Parser.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Cosmos/Internal/Parser.cs new file mode 100644 index 0000000..014c7fc --- /dev/null +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Cosmos/Internal/Parser.cs @@ -0,0 +1,23 @@ +namespace Masa.Utils.Data.EntityFrameworkCore.Cosmos.Internal; + +internal static class Parser +{ + public static Dictionary ToDictionary(this string connectionString) + { + if (string.IsNullOrEmpty(connectionString)) + throw new ArgumentException("Cosmos: empty database connection string", nameof(connectionString)); + + Dictionary dictionary = new(); + foreach (var item in connectionString.Split(';')) + { + if (string.IsNullOrEmpty(item)) + continue; + + if (item.Split('=').Length != 2) + throw new ArgumentException("Cosmos: Bad database connection string"); + + dictionary.Add(item.Split('=')[0], item.Split('=')[1]); + } + return dictionary; + } +} diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/README.md b/src/Data/Masa.Utils.Data.EntityFrameworkCore/README.md index 3305ecf..bc2f5ea 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/README.md +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/README.md @@ -23,7 +23,14 @@ builder.Services.AddMasaDbContext(optionsBuilder => Recommended usage: -[SqlServer](../Masa.Utils.Data.EntityFrameworkCore.SqlServer/README.md) +- [SqlServer](../Masa.Utils.Data.EntityFrameworkCore.SqlServer/README.md) +- [MySql](../Masa.Utils.Data.EntityFrameworkCore.MySql/README.md) +- [Pomelo.MySql](../Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql/README.md) +- [Sqlite](../Masa.Utils.Data.EntityFrameworkCore.Sqlite/README.md) +- [Cosmos](../Masa.Utils.Data.EntityFrameworkCore.Cosmos/README.md) +- [InMemory](../Masa.Utils.Data.EntityFrameworkCore.InMemory/README.md) +- [Oracle](../Masa.Utils.Data.EntityFrameworkCore.Oracle/README.md) +- [PostgreSql](../Masa.Utils.Data.EntityFrameworkCore.PostgreSql/README.md) #### data filter diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/README.zh-CN.md b/src/Data/Masa.Utils.Data.EntityFrameworkCore/README.zh-CN.md index c9e86de..fd855be 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/README.zh-CN.md +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/README.zh-CN.md @@ -6,7 +6,7 @@ ```c# Install-Package Masa.Utils.Data.EntityFrameworkCore -Install-Package Microsoft.EntityFrameworkCore.SqlServer +Install-Package Microsoft.EntityFrameworkCore.SqlServer//这里以SqlServer举例 ``` #### 基本用法: @@ -23,7 +23,14 @@ builder.Services.AddMasaDbContext(optionsBuilder => 推荐用法: -[SqlServer](../Masa.Utils.Data.EntityFrameworkCore.SqlServer/README.zh-CN.md) +- [SqlServer](../Masa.Utils.Data.EntityFrameworkCore.SqlServer/README.zh-CN.md) +- [MySql](../Masa.Utils.Data.EntityFrameworkCore.MySql/README.zh-CN.md) +- [Pomelo.MySql](../Masa.Utils.Data.EntityFrameworkCore.Pomelo.MySql/README.zh-CN.md) +- [Sqlite](../Masa.Utils.Data.EntityFrameworkCore.Sqlite/README.zh-CN.md) +- [Cosmos](../Masa.Utils.Data.EntityFrameworkCore.Cosmos/README.zh-CN.md) +- [InMemory](../Masa.Utils.Data.EntityFrameworkCore.InMemory/README.zh-CN.md) +- [Oracle](../Masa.Utils.Data.EntityFrameworkCore.Oracle/README.zh-CN.md) +- [PostgreSql](../Masa.Utils.Data.EntityFrameworkCore.PostgreSql/README.zh-CN.md) #### 数据过滤器 From 22265269fe67a21868fcaf55760760cffea38693 Mon Sep 17 00:00:00 2001 From: zhenlei520 Date: Fri, 18 Mar 2022 17:38:24 +0800 Subject: [PATCH 20/24] fix(EntityFrameworkCore): Fix MasaDbContext soft delete issue and circular dependency issue --- .../Filters/SoftDeleteSaveChangesFilter.cs | 8 +++----- .../MasaDbConnectionOptions.cs | 7 +------ .../MasaDbContext.cs | 13 +++++-------- .../MasaDbContextOptions`.cs | 16 ++++++++-------- .../ServiceCollectionExtensions.cs | 7 ++----- .../_Imports.cs | 1 + 6 files changed, 20 insertions(+), 32 deletions(-) diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/Filters/SoftDeleteSaveChangesFilter.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/Filters/SoftDeleteSaveChangesFilter.cs index 92f186c..56e5b7f 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/Filters/SoftDeleteSaveChangesFilter.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/Filters/SoftDeleteSaveChangesFilter.cs @@ -4,17 +4,15 @@ public class SoftDeleteSaveChangesFilter : ISaveChangesFilter { private readonly MasaDbContextOptions _masaDbContextOptions; - public SoftDeleteSaveChangesFilter(MasaDbContextOptions masaDbContextOptions) - => _masaDbContextOptions = masaDbContextOptions; + public SoftDeleteSaveChangesFilter(MasaDbContextOptions masaDbContextOptions) => _masaDbContextOptions = masaDbContextOptions; public void OnExecuting(ChangeTracker changeTracker) { - if(!_masaDbContextOptions.EnableSoftDelete) + if (!_masaDbContextOptions.EnableSoftDelete) return; changeTracker.DetectChanges(); - foreach (var entity in changeTracker.Entries().Where(entry => entry.State == EntityState.Deleted || - entry.State == EntityState.Added)) + foreach (var entity in changeTracker.Entries().Where(entry => entry.State == EntityState.Deleted)) { entity.State = EntityState.Modified; entity.CurrentValues[nameof(ISoftDelete.IsDeleted)] = true; diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbConnectionOptions.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbConnectionOptions.cs index 54651aa..c6a92d1 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbConnectionOptions.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbConnectionOptions.cs @@ -2,10 +2,5 @@ public class MasaDbConnectionOptions { - public MasaDbConnectionOptions(string defaultConnection) - { - DefaultConnection = defaultConnection; - } - - public string DefaultConnection { get; private set; } + public string DefaultConnection { get; set; } } diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContext.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContext.cs index 692f64a..0d5c427 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContext.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContext.cs @@ -19,10 +19,10 @@ public MasaDbContext(MasaDbContextOptions options) : base(options) /// protected sealed override void OnModelCreating(ModelBuilder modelBuilder) { - OnModelCreatingConfigureGlobalFilters(modelBuilder); - OnModelCreatingExecuting(modelBuilder); + OnModelCreatingConfigureGlobalFilters(modelBuilder); + // null when run dotnet ef cli if (Options == null) { @@ -45,8 +45,7 @@ protected virtual void OnModelCreatingExecuting(ModelBuilder modelBuilder) protected virtual void OnModelCreatingConfigureGlobalFilters(ModelBuilder modelBuilder) { - var methodInfo = typeof(MasaDbContext).GetMethod(nameof(ConfigureGlobalFilters), - BindingFlags.NonPublic | BindingFlags.Instance); + var methodInfo = typeof(MasaDbContext).GetMethod(nameof(ConfigureGlobalFilters), BindingFlags.NonPublic | BindingFlags.Instance); foreach (var entityType in modelBuilder.Model.GetEntityTypes()) { @@ -72,8 +71,7 @@ protected virtual void ConfigureGlobalFilters(ModelBuilder modelBuilder if (typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity))) { - expression = entity => !IsSoftDeleteFilterEnabled || - !EF.Property(entity, nameof(ISoftDelete.IsDeleted)); + expression = entity => !IsSoftDeleteFilterEnabled || !EF.Property(entity, nameof(ISoftDelete.IsDeleted)); } return expression; @@ -124,8 +122,7 @@ private void OnFilterExecuting() /// /// /// - public override Task SaveChangesAsync(CancellationToken cancellationToken = default) - => SaveChangesAsync(true, cancellationToken); + public override Task SaveChangesAsync(CancellationToken cancellationToken = default) => SaveChangesAsync(true, cancellationToken); /// /// Automatic soft delete. diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptions`.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptions`.cs index e553ea0..1248062 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptions`.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/MasaDbContextOptions`.cs @@ -8,22 +8,22 @@ public class MasaDbContextOptions : MasaDbContextOptions public MasaDbContextOptions( IServiceProvider serviceProvider, DbContextOptions originOptions, - bool enableSoftDelete) : base(serviceProvider, enableSoftDelete) - { - _originOptions = originOptions; - ModelCreatingProviders = ServiceProvider.GetServices(); - SaveChangesFilters = ServiceProvider.GetServices(); - } + bool enableSoftDelete) : base(serviceProvider, enableSoftDelete) => _originOptions = originOptions; + + private IEnumerable? _modelCreatingProviders; /// /// Can be used to filter data /// - public override IEnumerable ModelCreatingProviders { get; } + public override IEnumerable ModelCreatingProviders => _modelCreatingProviders ??= ServiceProvider.GetServices(); + + + private IEnumerable? _saveChangesFilters; /// /// Can be used to intercept SaveChanges(Async) method /// - public override IEnumerable SaveChangesFilters { get; } + public override IEnumerable SaveChangesFilters => _saveChangesFilters ??= ServiceProvider.GetServices(); /// /// diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/ServiceCollectionExtensions.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/ServiceCollectionExtensions.cs index c4e69fa..43c1ef2 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/ServiceCollectionExtensions.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/ServiceCollectionExtensions.cs @@ -83,15 +83,12 @@ private static IServiceCollection TryAddConfigure( if (configuration == null) return services; - string name = typeof(TOptions).FullName ?? typeof(TOptions).Name; + string name = Options.DefaultName; services.AddOptions(); var configurationSection = configuration.GetSection(sectionName); services.TryAddSingleton>( new ConfigurationChangeTokenSource(name, configurationSection)); - services.TryAddSingleton>(new NamedConfigureFromConfigurationOptions(name, - configurationSection, _ => - { - })); + services.TryAddSingleton>(new NamedConfigureFromConfigurationOptions(name, configurationSection, _ => { })); return services; } } diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/_Imports.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/_Imports.cs index 1058752..db7403a 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/_Imports.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/_Imports.cs @@ -10,4 +10,5 @@ global using System.Collections.Concurrent; global using System.Linq.Expressions; global using System.Reflection; +global using Masa.Utils.Data.EntityFrameworkCore.Filters; From da209ffe5be2ceec6f15fd13aee100e1a86b65f2 Mon Sep 17 00:00:00 2001 From: zhenlei520 Date: Fri, 18 Mar 2022 17:38:47 +0800 Subject: [PATCH 21/24] test(EntityFrameworkCore): Add EntityFrameworkCore UnitTest --- Masa.Utils.sln | 7 ++ ...tils.Data.EntityFrameworkCore.Tests.csproj | 34 ++++++ .../MasaDbContextTests.cs | 100 ++++++++++++++++++ .../Models/Student.cs | 12 +++ .../TestDbContext.cs | 13 +++ .../_Imports.cs | 7 ++ .../appsettings.json | 5 + 7 files changed, 178 insertions(+) create mode 100644 test/Masa.Utils.Data.EntityFrameworkCore.Tests/Masa.Utils.Data.EntityFrameworkCore.Tests.csproj create mode 100644 test/Masa.Utils.Data.EntityFrameworkCore.Tests/MasaDbContextTests.cs create mode 100644 test/Masa.Utils.Data.EntityFrameworkCore.Tests/Models/Student.cs create mode 100644 test/Masa.Utils.Data.EntityFrameworkCore.Tests/TestDbContext.cs create mode 100644 test/Masa.Utils.Data.EntityFrameworkCore.Tests/_Imports.cs create mode 100644 test/Masa.Utils.Data.EntityFrameworkCore.Tests/appsettings.json diff --git a/Masa.Utils.sln b/Masa.Utils.sln index 3bc7e9d..08d8057 100644 --- a/Masa.Utils.sln +++ b/Masa.Utils.sln @@ -101,6 +101,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Data.EntityFrame EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Data.EntityFrameworkCore.Cosmos", "src\Data\Masa.Utils.Data.EntityFrameworkCore.Cosmos\Masa.Utils.Data.EntityFrameworkCore.Cosmos.csproj", "{B8CB480B-2608-46A8-8528-37EDD5E1EC1E}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Masa.Utils.Data.EntityFrameworkCore.Tests", "test\Masa.Utils.Data.EntityFrameworkCore.Tests\Masa.Utils.Data.EntityFrameworkCore.Tests.csproj", "{41C2A208-4DF8-4BD0-B844-77E6F58FE000}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -251,6 +253,10 @@ Global {B8CB480B-2608-46A8-8528-37EDD5E1EC1E}.Debug|Any CPU.Build.0 = Debug|Any CPU {B8CB480B-2608-46A8-8528-37EDD5E1EC1E}.Release|Any CPU.ActiveCfg = Release|Any CPU {B8CB480B-2608-46A8-8528-37EDD5E1EC1E}.Release|Any CPU.Build.0 = Release|Any CPU + {41C2A208-4DF8-4BD0-B844-77E6F58FE000}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {41C2A208-4DF8-4BD0-B844-77E6F58FE000}.Debug|Any CPU.Build.0 = Debug|Any CPU + {41C2A208-4DF8-4BD0-B844-77E6F58FE000}.Release|Any CPU.ActiveCfg = Release|Any CPU + {41C2A208-4DF8-4BD0-B844-77E6F58FE000}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -300,6 +306,7 @@ Global {D682F08B-6586-4C33-815D-8F98C50A0843} = {F844C2A1-C36D-400E-A0D8-7658EF9C3B93} {2AB5DFD8-B537-4066-8366-E3F371BD5EE2} = {F844C2A1-C36D-400E-A0D8-7658EF9C3B93} {B8CB480B-2608-46A8-8528-37EDD5E1EC1E} = {F844C2A1-C36D-400E-A0D8-7658EF9C3B93} + {41C2A208-4DF8-4BD0-B844-77E6F58FE000} = {4F908878-0EB8-43E4-96E4-8B1F32E9B635} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {D7DAA0E6-098F-4B18-8775-64FDA96F1FF0} diff --git a/test/Masa.Utils.Data.EntityFrameworkCore.Tests/Masa.Utils.Data.EntityFrameworkCore.Tests.csproj b/test/Masa.Utils.Data.EntityFrameworkCore.Tests/Masa.Utils.Data.EntityFrameworkCore.Tests.csproj new file mode 100644 index 0000000..83db83d --- /dev/null +++ b/test/Masa.Utils.Data.EntityFrameworkCore.Tests/Masa.Utils.Data.EntityFrameworkCore.Tests.csproj @@ -0,0 +1,34 @@ + + + + net6.0 + enable + enable + false + Masa.Utils.Data.EntityFrameworkCore.Test + + + + + + + + + + + + + + + + + + + + + + Always + + + + diff --git a/test/Masa.Utils.Data.EntityFrameworkCore.Tests/MasaDbContextTests.cs b/test/Masa.Utils.Data.EntityFrameworkCore.Tests/MasaDbContextTests.cs new file mode 100644 index 0000000..49926f9 --- /dev/null +++ b/test/Masa.Utils.Data.EntityFrameworkCore.Tests/MasaDbContextTests.cs @@ -0,0 +1,100 @@ +namespace Masa.Utils.Data.EntityFrameworkCore.Test; + +[TestClass] +public class MasaDbContextTests +{ + private readonly IServiceCollection _services; + + public MasaDbContextTests() + { + _services = new ServiceCollection(); + var configurationRoot = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("appsettings.json", true, true) + .Build(); + _services.AddSingleton(configurationRoot); + } + + [TestMethod] + public async Task TestAddAsync() + { + var dbContext = CreateDbContext(true, out _); + await dbContext.Set().AddAsync(new Student() + { + Id = 1, + Name = "Jim", + Age = 18, + }); + await dbContext.SaveChangesAsync(); + Assert.IsTrue(await dbContext.Set().CountAsync() == 1); + } + + [TestMethod] + public async Task TestSoftDeleteAsync() + { + var dbContext = CreateDbContext(true, out IServiceProvider serviceProvider); + var student = new Student() + { + Id = 1, + Name = "Jim", + Age = 18, + }; + await dbContext.Set().AddAsync(student); + await dbContext.SaveChangesAsync(); + Assert.IsTrue(await dbContext.Set().CountAsync() == 1); + + dbContext.Set().Remove(student); + await dbContext.SaveChangesAsync(); + + Assert.IsTrue(await dbContext.Set().CountAsync() == 0); + + var dataFilter = serviceProvider.GetRequiredService(); + using (dataFilter.Disable()) + { + Assert.IsTrue(await dbContext.Set().CountAsync() == 1); + + student = (await dbContext.Set().FirstOrDefaultAsync())!; + Assert.IsTrue(student.Id == 1); + Assert.IsTrue(student.Name == "Jim"); + Assert.IsTrue(student.Age == 18); + Assert.IsTrue(student.IsDeleted); + } + } + + [TestMethod] + public async Task TestDisabledSoftware() + { + var dbContext = CreateDbContext(false, out IServiceProvider serviceProvider); + var student = new Student() + { + Id = 1, + Name = "Jim", + Age = 18, + }; + await dbContext.Set().AddAsync(student); + await dbContext.SaveChangesAsync(); + Assert.IsTrue(await dbContext.Set().CountAsync() == 1); + + dbContext.Set().Remove(student); + await dbContext.SaveChangesAsync(); + + Assert.IsTrue(await dbContext.Set().CountAsync() == 0); + + var dataFilter = serviceProvider.GetRequiredService(); + using (dataFilter.Disable()) + Assert.IsTrue(await dbContext.Set().CountAsync() == 0); + } + + private TestDbContext CreateDbContext(bool enableSoftware, out IServiceProvider serviceProvider) + { + _services.AddMasaDbContext(options => + { + if (enableSoftware) + options.UseSoftDelete(); + + options.UseInMemoryDatabase(); + }); + serviceProvider = _services.BuildServiceProvider(); + return serviceProvider.GetRequiredService(); + } +} diff --git a/test/Masa.Utils.Data.EntityFrameworkCore.Tests/Models/Student.cs b/test/Masa.Utils.Data.EntityFrameworkCore.Tests/Models/Student.cs new file mode 100644 index 0000000..e810183 --- /dev/null +++ b/test/Masa.Utils.Data.EntityFrameworkCore.Tests/Models/Student.cs @@ -0,0 +1,12 @@ +namespace Masa.Utils.Data.EntityFrameworkCore.Test.Models; + +public class Student : ISoftDelete +{ + public int Id { get; set; } + + public string Name { get; set; } + + public int Age { get; set; } + + public bool IsDeleted { get; private set; } +} diff --git a/test/Masa.Utils.Data.EntityFrameworkCore.Tests/TestDbContext.cs b/test/Masa.Utils.Data.EntityFrameworkCore.Tests/TestDbContext.cs new file mode 100644 index 0000000..af93eef --- /dev/null +++ b/test/Masa.Utils.Data.EntityFrameworkCore.Tests/TestDbContext.cs @@ -0,0 +1,13 @@ +namespace Masa.Utils.Data.EntityFrameworkCore.Test; + +public class TestDbContext : MasaDbContext +{ + public TestDbContext(MasaDbContextOptions options) : base(options) + { + } + + protected override void OnModelCreatingExecuting(ModelBuilder modelBuilder) + { + modelBuilder.Entity(); + } +} diff --git a/test/Masa.Utils.Data.EntityFrameworkCore.Tests/_Imports.cs b/test/Masa.Utils.Data.EntityFrameworkCore.Tests/_Imports.cs new file mode 100644 index 0000000..1cf907c --- /dev/null +++ b/test/Masa.Utils.Data.EntityFrameworkCore.Tests/_Imports.cs @@ -0,0 +1,7 @@ +global using Masa.Utils.Data.EntityFrameworkCore.Filters; +global using Masa.Utils.Data.EntityFrameworkCore.InMemory; +global using Masa.Utils.Data.EntityFrameworkCore.Test.Models; +global using Microsoft.EntityFrameworkCore; +global using Microsoft.Extensions.Configuration; +global using Microsoft.Extensions.DependencyInjection; +global using Microsoft.VisualStudio.TestTools.UnitTesting; diff --git a/test/Masa.Utils.Data.EntityFrameworkCore.Tests/appsettings.json b/test/Masa.Utils.Data.EntityFrameworkCore.Tests/appsettings.json new file mode 100644 index 0000000..c75b4c1 --- /dev/null +++ b/test/Masa.Utils.Data.EntityFrameworkCore.Tests/appsettings.json @@ -0,0 +1,5 @@ +{ + "ConnectionStrings": { + "DefaultConnection": "test" + } +} \ No newline at end of file From b7543730cb09a1f76a237decdd337ac2adb8b434 Mon Sep 17 00:00:00 2001 From: zhenlei520 Date: Fri, 18 Mar 2022 19:43:01 +0800 Subject: [PATCH 22/24] test(EntityFramework): Improve EntityFramework unit tests --- .../ConnectionStringProvider.cs | 8 ++++ .../CustomMasaDbContextTest.cs | 40 +++++++++++++++++ .../MasaDbContextTests.cs | 43 ++++++------------- .../Models/Student.cs | 2 +- .../TestBase.cs | 29 +++++++++++++ .../_Imports.cs | 3 ++ 6 files changed, 93 insertions(+), 32 deletions(-) create mode 100644 test/Masa.Utils.Data.EntityFrameworkCore.Tests/ConnectionStringProvider.cs create mode 100644 test/Masa.Utils.Data.EntityFrameworkCore.Tests/CustomMasaDbContextTest.cs create mode 100644 test/Masa.Utils.Data.EntityFrameworkCore.Tests/TestBase.cs diff --git a/test/Masa.Utils.Data.EntityFrameworkCore.Tests/ConnectionStringProvider.cs b/test/Masa.Utils.Data.EntityFrameworkCore.Tests/ConnectionStringProvider.cs new file mode 100644 index 0000000..adc6245 --- /dev/null +++ b/test/Masa.Utils.Data.EntityFrameworkCore.Tests/ConnectionStringProvider.cs @@ -0,0 +1,8 @@ +namespace Masa.Utils.Data.EntityFrameworkCore.Test; + +public class ConnectionStringProvider : IConnectionStringProvider +{ + public Task GetConnectionStringAsync() => Task.FromResult(GetConnectionString()); + + public string GetConnectionString() => "custom"; +} diff --git a/test/Masa.Utils.Data.EntityFrameworkCore.Tests/CustomMasaDbContextTest.cs b/test/Masa.Utils.Data.EntityFrameworkCore.Tests/CustomMasaDbContextTest.cs new file mode 100644 index 0000000..653063f --- /dev/null +++ b/test/Masa.Utils.Data.EntityFrameworkCore.Tests/CustomMasaDbContextTest.cs @@ -0,0 +1,40 @@ +namespace Masa.Utils.Data.EntityFrameworkCore.Test; + +[TestClass] +public class TestCustomMasaDbContextTest : TestBase +{ + [TestMethod] + public void TestCustomDatabase() + { + Services.AddScoped(); + var dbContext = CreateDbContext(false, out IServiceProvider serviceProvider); + Assert.IsTrue(GetDatabaseName(dbContext) == "custom"); + } + + [TestMethod] + public void TestCustomDatabase2() + { + Services.Configure(options => + { + options.DefaultConnection = "user"; + }); + var dbContext = CreateDbContext(false, out IServiceProvider serviceProvider); + Assert.IsTrue(GetDatabaseName(dbContext) == "user"); + } + + private string GetDatabaseName(DbContext dbContext) + { + FieldInfo fieldInfo = + dbContext.GetType().GetField("Options", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)!; + MasaDbContextOptions masaDbContextOptions = (fieldInfo.GetValue(dbContext) as MasaDbContextOptions)!; + + foreach (var dbContextOptionsExtension in masaDbContextOptions.Extensions) + { + if (dbContextOptionsExtension is InMemoryOptionsExtension inMemoryOptionsExtension) + { + return inMemoryOptionsExtension.StoreName; + } + } + return string.Empty; + } +} diff --git a/test/Masa.Utils.Data.EntityFrameworkCore.Tests/MasaDbContextTests.cs b/test/Masa.Utils.Data.EntityFrameworkCore.Tests/MasaDbContextTests.cs index 49926f9..a5e00ba 100644 --- a/test/Masa.Utils.Data.EntityFrameworkCore.Tests/MasaDbContextTests.cs +++ b/test/Masa.Utils.Data.EntityFrameworkCore.Tests/MasaDbContextTests.cs @@ -1,24 +1,12 @@ namespace Masa.Utils.Data.EntityFrameworkCore.Test; [TestClass] -public class MasaDbContextTests +public class MasaDbContextTests : TestBase { - private readonly IServiceCollection _services; - - public MasaDbContextTests() - { - _services = new ServiceCollection(); - var configurationRoot = new ConfigurationBuilder() - .SetBasePath(Directory.GetCurrentDirectory()) - .AddJsonFile("appsettings.json", true, true) - .Build(); - _services.AddSingleton(configurationRoot); - } - [TestMethod] public async Task TestAddAsync() { - var dbContext = CreateDbContext(true, out _); + await using var dbContext = CreateDbContext(true, out _); await dbContext.Set().AddAsync(new Student() { Id = 1, @@ -32,7 +20,11 @@ await dbContext.Set().AddAsync(new Student() [TestMethod] public async Task TestSoftDeleteAsync() { - var dbContext = CreateDbContext(true, out IServiceProvider serviceProvider); + Services.Configure(options => + { + options.DefaultConnection = "soft-delete-db"; + }); + await using var dbContext = CreateDbContext(true, out IServiceProvider serviceProvider); var student = new Student() { Id = 1, @@ -62,10 +54,12 @@ public async Task TestSoftDeleteAsync() } [TestMethod] - public async Task TestDisabledSoftware() + public async Task TestDisabledSoftDelete() { - var dbContext = CreateDbContext(false, out IServiceProvider serviceProvider); - var student = new Student() + Services.AddMasaDbContext(options => options.UseInMemoryDatabase("disabled-soft-delete-db")); + var serviceProvider = Services.BuildServiceProvider(); + var dbContext = serviceProvider.GetRequiredService(); + var student = new Student { Id = 1, Name = "Jim", @@ -84,17 +78,4 @@ public async Task TestDisabledSoftware() using (dataFilter.Disable()) Assert.IsTrue(await dbContext.Set().CountAsync() == 0); } - - private TestDbContext CreateDbContext(bool enableSoftware, out IServiceProvider serviceProvider) - { - _services.AddMasaDbContext(options => - { - if (enableSoftware) - options.UseSoftDelete(); - - options.UseInMemoryDatabase(); - }); - serviceProvider = _services.BuildServiceProvider(); - return serviceProvider.GetRequiredService(); - } } diff --git a/test/Masa.Utils.Data.EntityFrameworkCore.Tests/Models/Student.cs b/test/Masa.Utils.Data.EntityFrameworkCore.Tests/Models/Student.cs index e810183..8f8721b 100644 --- a/test/Masa.Utils.Data.EntityFrameworkCore.Tests/Models/Student.cs +++ b/test/Masa.Utils.Data.EntityFrameworkCore.Tests/Models/Student.cs @@ -4,7 +4,7 @@ public class Student : ISoftDelete { public int Id { get; set; } - public string Name { get; set; } + public string Name { get; set; } = default!; public int Age { get; set; } diff --git a/test/Masa.Utils.Data.EntityFrameworkCore.Tests/TestBase.cs b/test/Masa.Utils.Data.EntityFrameworkCore.Tests/TestBase.cs new file mode 100644 index 0000000..80c90f3 --- /dev/null +++ b/test/Masa.Utils.Data.EntityFrameworkCore.Tests/TestBase.cs @@ -0,0 +1,29 @@ +namespace Masa.Utils.Data.EntityFrameworkCore.Test; + +public class TestBase +{ + protected readonly IServiceCollection Services; + + public TestBase() + { + Services = new ServiceCollection(); + var configurationRoot = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("appsettings.json", true, true) + .Build(); + Services.AddSingleton(configurationRoot); + } + + protected TestDbContext CreateDbContext(bool enableSoftDelete, out IServiceProvider serviceProvider) + { + Services.AddMasaDbContext(options => + { + if (enableSoftDelete) + options.UseSoftDelete(); + + options.UseInMemoryDatabase(); + }); + serviceProvider = Services.BuildServiceProvider(); + return serviceProvider.GetRequiredService(); + } +} diff --git a/test/Masa.Utils.Data.EntityFrameworkCore.Tests/_Imports.cs b/test/Masa.Utils.Data.EntityFrameworkCore.Tests/_Imports.cs index 1cf907c..aa701a6 100644 --- a/test/Masa.Utils.Data.EntityFrameworkCore.Tests/_Imports.cs +++ b/test/Masa.Utils.Data.EntityFrameworkCore.Tests/_Imports.cs @@ -5,3 +5,6 @@ global using Microsoft.Extensions.Configuration; global using Microsoft.Extensions.DependencyInjection; global using Microsoft.VisualStudio.TestTools.UnitTesting; +global using System.Reflection; +global using Microsoft.EntityFrameworkCore.InMemory.Infrastructure.Internal; + From 73b91dae6843cf16507fc8652d1c70eabb223f81 Mon Sep 17 00:00:00 2001 From: zhenlei520 Date: Fri, 18 Mar 2022 19:48:45 +0800 Subject: [PATCH 23/24] chore: Modify Masa.Utils.Data.EntityFrameworkCore.Cosmos English document and global reference ordering --- src/Data/Masa.Utils.Data.EntityFrameworkCore.Cosmos/README.md | 2 +- .../Masa.Utils.Data.EntityFrameworkCore.Cosmos/_Imports.cs | 2 +- test/Masa.Utils.Data.EntityFrameworkCore.Tests/_Imports.cs | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.Cosmos/README.md b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Cosmos/README.md index 6689145..5841ec0 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore.Cosmos/README.md +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Cosmos/README.md @@ -15,7 +15,7 @@ Install-Package Masa.Utils.Data.EntityFrameworkCore.Cosmos ``` appsettings.json { "ConnectionStrings": { - "DefaultConnection": "AccountKey=AccountKey;AccountEndpoint=AccountEndpoint;Database=Database"//或"ConnectionString=ConnectionString;Database=Database" + "DefaultConnection": "AccountKey=AccountKey;AccountEndpoint=AccountEndpoint;Database=Database"// or "ConnectionString=ConnectionString;Database=Database" } } ``` diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore.Cosmos/_Imports.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Cosmos/_Imports.cs index 3f8ac7f..ce597c5 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore.Cosmos/_Imports.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore.Cosmos/_Imports.cs @@ -1,4 +1,4 @@ +global using Masa.Utils.Data.EntityFrameworkCore.Cosmos.Internal; global using Microsoft.EntityFrameworkCore; global using Microsoft.EntityFrameworkCore.Infrastructure; global using Microsoft.Extensions.DependencyInjection; -global using Masa.Utils.Data.EntityFrameworkCore.Cosmos.Internal; diff --git a/test/Masa.Utils.Data.EntityFrameworkCore.Tests/_Imports.cs b/test/Masa.Utils.Data.EntityFrameworkCore.Tests/_Imports.cs index aa701a6..d27b729 100644 --- a/test/Masa.Utils.Data.EntityFrameworkCore.Tests/_Imports.cs +++ b/test/Masa.Utils.Data.EntityFrameworkCore.Tests/_Imports.cs @@ -2,9 +2,8 @@ global using Masa.Utils.Data.EntityFrameworkCore.InMemory; global using Masa.Utils.Data.EntityFrameworkCore.Test.Models; global using Microsoft.EntityFrameworkCore; +global using Microsoft.EntityFrameworkCore.InMemory.Infrastructure.Internal; global using Microsoft.Extensions.Configuration; global using Microsoft.Extensions.DependencyInjection; global using Microsoft.VisualStudio.TestTools.UnitTesting; global using System.Reflection; -global using Microsoft.EntityFrameworkCore.InMemory.Infrastructure.Internal; - From 82489e91e904f2e64e25f8ff9223c640a8fc4e57 Mon Sep 17 00:00:00 2001 From: zhenlei520 Date: Fri, 18 Mar 2022 19:57:40 +0800 Subject: [PATCH 24/24] chore(EntityFrameworkCore): change parameter name --- .../Masa.Utils.Data.EntityFrameworkCore/Internal/Const.cs | 4 ++-- .../ServiceCollectionExtensions.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/Internal/Const.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/Internal/Const.cs index 026fb75..e7055d4 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/Internal/Const.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/Internal/Const.cs @@ -1,6 +1,6 @@ -namespace Masa.Utils.Data.EntityFrameworkCore.Internal; +namespace Masa.Utils.Data.EntityFrameworkCore.Internal; internal class Const { - public const string DefaultSection = "ConnectionStrings"; + public const string DEFAULT_SECTION = "ConnectionStrings"; } diff --git a/src/Data/Masa.Utils.Data.EntityFrameworkCore/ServiceCollectionExtensions.cs b/src/Data/Masa.Utils.Data.EntityFrameworkCore/ServiceCollectionExtensions.cs index 43c1ef2..656a915 100644 --- a/src/Data/Masa.Utils.Data.EntityFrameworkCore/ServiceCollectionExtensions.cs +++ b/src/Data/Masa.Utils.Data.EntityFrameworkCore/ServiceCollectionExtensions.cs @@ -72,7 +72,7 @@ private static MasaDbContextOptions CreateMasaDbContextOptions( this IServiceCollection services) where TOptions : class - => services.TryAddConfigure(Const.DefaultSection); + => services.TryAddConfigure(Const.DEFAULT_SECTION); private static IServiceCollection TryAddConfigure( this IServiceCollection services,