diff --git a/modules/settingmanagement/README.md b/modules/settingmanagement/README.md
new file mode 100644
index 0000000000..9d3f9b72b4
--- /dev/null
+++ b/modules/settingmanagement/README.md
@@ -0,0 +1,2 @@
+# abp-settingmanagement
+Setting management module for ABP framework.
diff --git a/modules/settingmanagement/Volo.Abp.SettingManagement.sln b/modules/settingmanagement/Volo.Abp.SettingManagement.sln
new file mode 100644
index 0000000000..fc870e1e80
--- /dev/null
+++ b/modules/settingmanagement/Volo.Abp.SettingManagement.sln
@@ -0,0 +1,81 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.27428.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.SettingManagement.Domain.Shared", "src\Volo.Abp.SettingManagement.Domain.Shared\Volo.Abp.SettingManagement.Domain.Shared.csproj", "{3A607A96-8248-4027-9A96-44145A84B210}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{F1BE945B-F0CF-4712-BC2B-9AF8C02059EA}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.SettingManagement.Domain", "src\Volo.Abp.SettingManagement.Domain\Volo.Abp.SettingManagement.Domain.csproj", "{5236093A-E52E-4D50-89B3-09591D35C2FA}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.SettingManagement.EntityFrameworkCore", "src\Volo.Abp.SettingManagement.EntityFrameworkCore\Volo.Abp.SettingManagement.EntityFrameworkCore.csproj", "{10A31B5C-B772-4F78-94A9-FE49A15D068D}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{7E8D2943-ADE7-4C89-8048-0780CE07E0E0}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.SettingManagement.Tests", "test\Volo.Abp.SettingManagement.Tests\Volo.Abp.SettingManagement.Tests.csproj", "{E8335ADC-D09E-4B74-8190-45A9FAF962CA}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.SettingManagement.MongoDB", "src\Volo.Abp.SettingManagement.MongoDB\Volo.Abp.SettingManagement.MongoDB.csproj", "{7615D255-FB8F-49F0-81C0-F2E69F7F0CB7}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.SettingManagement.TestBase", "test\Volo.Abp.SettingManagement.TestBase\Volo.Abp.SettingManagement.TestBase.csproj", "{D4A2DCB2-FA6A-43DC-9469-B6CDAA7EB489}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.SettingManagement.EntityFrameworkCore.Tests", "test\Volo.Abp.SettingManagement.EntityFrameworkCore.Tests\Volo.Abp.SettingManagement.EntityFrameworkCore.Tests.csproj", "{AFF6A7B6-A80B-4569-9F6B-CD6C72EAB6D4}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.SettingManagement.MongoDB.Tests", "test\Volo.Abp.SettingManagement.MongoDB.Tests\Volo.Abp.SettingManagement.MongoDB.Tests.csproj", "{DF76DE74-1029-4FEA-8ADF-3C5636944757}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {3A607A96-8248-4027-9A96-44145A84B210}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3A607A96-8248-4027-9A96-44145A84B210}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3A607A96-8248-4027-9A96-44145A84B210}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3A607A96-8248-4027-9A96-44145A84B210}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5236093A-E52E-4D50-89B3-09591D35C2FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5236093A-E52E-4D50-89B3-09591D35C2FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5236093A-E52E-4D50-89B3-09591D35C2FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5236093A-E52E-4D50-89B3-09591D35C2FA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {10A31B5C-B772-4F78-94A9-FE49A15D068D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {10A31B5C-B772-4F78-94A9-FE49A15D068D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {10A31B5C-B772-4F78-94A9-FE49A15D068D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {10A31B5C-B772-4F78-94A9-FE49A15D068D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E8335ADC-D09E-4B74-8190-45A9FAF962CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E8335ADC-D09E-4B74-8190-45A9FAF962CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E8335ADC-D09E-4B74-8190-45A9FAF962CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E8335ADC-D09E-4B74-8190-45A9FAF962CA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7615D255-FB8F-49F0-81C0-F2E69F7F0CB7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7615D255-FB8F-49F0-81C0-F2E69F7F0CB7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7615D255-FB8F-49F0-81C0-F2E69F7F0CB7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7615D255-FB8F-49F0-81C0-F2E69F7F0CB7}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D4A2DCB2-FA6A-43DC-9469-B6CDAA7EB489}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D4A2DCB2-FA6A-43DC-9469-B6CDAA7EB489}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D4A2DCB2-FA6A-43DC-9469-B6CDAA7EB489}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D4A2DCB2-FA6A-43DC-9469-B6CDAA7EB489}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AFF6A7B6-A80B-4569-9F6B-CD6C72EAB6D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AFF6A7B6-A80B-4569-9F6B-CD6C72EAB6D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AFF6A7B6-A80B-4569-9F6B-CD6C72EAB6D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AFF6A7B6-A80B-4569-9F6B-CD6C72EAB6D4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DF76DE74-1029-4FEA-8ADF-3C5636944757}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DF76DE74-1029-4FEA-8ADF-3C5636944757}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DF76DE74-1029-4FEA-8ADF-3C5636944757}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DF76DE74-1029-4FEA-8ADF-3C5636944757}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {3A607A96-8248-4027-9A96-44145A84B210} = {F1BE945B-F0CF-4712-BC2B-9AF8C02059EA}
+ {5236093A-E52E-4D50-89B3-09591D35C2FA} = {F1BE945B-F0CF-4712-BC2B-9AF8C02059EA}
+ {10A31B5C-B772-4F78-94A9-FE49A15D068D} = {F1BE945B-F0CF-4712-BC2B-9AF8C02059EA}
+ {E8335ADC-D09E-4B74-8190-45A9FAF962CA} = {7E8D2943-ADE7-4C89-8048-0780CE07E0E0}
+ {7615D255-FB8F-49F0-81C0-F2E69F7F0CB7} = {F1BE945B-F0CF-4712-BC2B-9AF8C02059EA}
+ {D4A2DCB2-FA6A-43DC-9469-B6CDAA7EB489} = {7E8D2943-ADE7-4C89-8048-0780CE07E0E0}
+ {AFF6A7B6-A80B-4569-9F6B-CD6C72EAB6D4} = {7E8D2943-ADE7-4C89-8048-0780CE07E0E0}
+ {DF76DE74-1029-4FEA-8ADF-3C5636944757} = {7E8D2943-ADE7-4C89-8048-0780CE07E0E0}
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {24B3A486-E7CA-4AA5-B76F-27D351A97E59}
+ EndGlobalSection
+EndGlobal
diff --git a/modules/settingmanagement/common.props b/modules/settingmanagement/common.props
new file mode 100644
index 0000000000..f00a3fc2cb
--- /dev/null
+++ b/modules/settingmanagement/common.props
@@ -0,0 +1,16 @@
+
+
+ latest
+ 0.3.0
+ $(NoWarn);CS1591
+ http://www.aspnetboilerplate.com/images/abp_nupkg.png
+ http://abp.io
+ git
+ https://github.com/volosoft/abp/
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/settingmanagement/src/Volo.Abp.SettingManagement.Domain.Shared/Volo.Abp.SettingManagement.Domain.Shared.csproj b/modules/settingmanagement/src/Volo.Abp.SettingManagement.Domain.Shared/Volo.Abp.SettingManagement.Domain.Shared.csproj
new file mode 100644
index 0000000000..f2dccdfe14
--- /dev/null
+++ b/modules/settingmanagement/src/Volo.Abp.SettingManagement.Domain.Shared/Volo.Abp.SettingManagement.Domain.Shared.csproj
@@ -0,0 +1,20 @@
+
+
+
+
+
+ netstandard2.0
+ Volo.Abp.SettingManagement.Domain.Shared
+ Volo.Abp.SettingManagement.Domain.Shared
+ $(AssetTargetFallback);portable-net45+win8+wp8+wpa81;
+ false
+ false
+ false
+
+
+
+
+
+
+
+
diff --git a/modules/settingmanagement/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/AbpSettingManagementDomainSharedModule.cs b/modules/settingmanagement/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/AbpSettingManagementDomainSharedModule.cs
new file mode 100644
index 0000000000..d489813551
--- /dev/null
+++ b/modules/settingmanagement/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/AbpSettingManagementDomainSharedModule.cs
@@ -0,0 +1,13 @@
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.Modularity;
+
+namespace Volo.Abp.SettingManagement
+{
+ public class AbpSettingManagementDomainSharedModule : AbpModule
+ {
+ public override void ConfigureServices(IServiceCollection services)
+ {
+ services.AddAssemblyOf();
+ }
+ }
+}
diff --git a/modules/settingmanagement/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/SettingConsts.cs b/modules/settingmanagement/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/SettingConsts.cs
new file mode 100644
index 0000000000..0b92e24ece
--- /dev/null
+++ b/modules/settingmanagement/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/SettingConsts.cs
@@ -0,0 +1,10 @@
+namespace Volo.Abp.SettingManagement
+{
+ public static class SettingConsts
+ {
+ public const int MaxNameLength = 128;
+ public const int MaxValueLength = 2048;
+ public const int MaxProviderNameLength = 64;
+ public const int MaxProviderKeyLength = 64;
+ }
+}
diff --git a/modules/settingmanagement/src/Volo.Abp.SettingManagement.Domain/Volo.Abp.SettingManagement.Domain.csproj b/modules/settingmanagement/src/Volo.Abp.SettingManagement.Domain/Volo.Abp.SettingManagement.Domain.csproj
new file mode 100644
index 0000000000..44b5d8ead2
--- /dev/null
+++ b/modules/settingmanagement/src/Volo.Abp.SettingManagement.Domain/Volo.Abp.SettingManagement.Domain.csproj
@@ -0,0 +1,23 @@
+
+
+
+
+
+ netstandard2.0
+ Volo.Abp.SettingManagement.Domain
+ Volo.Abp.SettingManagement.Domain
+ $(AssetTargetFallback);portable-net45+win8+wp8+wpa81;
+ false
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/settingmanagement/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/AbpSettingManagementConsts.cs b/modules/settingmanagement/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/AbpSettingManagementConsts.cs
new file mode 100644
index 0000000000..aaae54f69d
--- /dev/null
+++ b/modules/settingmanagement/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/AbpSettingManagementConsts.cs
@@ -0,0 +1,9 @@
+namespace Volo.Abp.SettingManagement
+{
+ public static class AbpSettingManagementConsts
+ {
+ public const string DefaultDbTablePrefix = "Abp";
+
+ public const string DefaultDbSchema = null;
+ }
+}
diff --git a/modules/settingmanagement/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/AbpSettingManagementDomainModule.cs b/modules/settingmanagement/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/AbpSettingManagementDomainModule.cs
new file mode 100644
index 0000000000..52522a69f6
--- /dev/null
+++ b/modules/settingmanagement/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/AbpSettingManagementDomainModule.cs
@@ -0,0 +1,18 @@
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.Domain;
+using Volo.Abp.Modularity;
+using Volo.Abp.Settings;
+
+namespace Volo.Abp.SettingManagement
+{
+ [DependsOn(typeof(AbpSettingsModule))]
+ [DependsOn(typeof(AbpDddDomainModule))]
+ [DependsOn(typeof(AbpSettingManagementDomainSharedModule))]
+ public class AbpSettingManagementDomainModule : AbpModule
+ {
+ public override void ConfigureServices(IServiceCollection services)
+ {
+ services.AddAssemblyOf();
+ }
+ }
+}
diff --git a/modules/settingmanagement/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/ISettingRepository.cs b/modules/settingmanagement/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/ISettingRepository.cs
new file mode 100644
index 0000000000..6eeffae426
--- /dev/null
+++ b/modules/settingmanagement/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/ISettingRepository.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Volo.Abp.Domain.Repositories;
+
+namespace Volo.Abp.SettingManagement
+{
+ public interface ISettingRepository : IBasicRepository
+ {
+ Task FindAsync(string name, string providerName, string providerKey);
+
+ Task> GetListAsync(string providerName, string providerKey);
+ }
+}
\ No newline at end of file
diff --git a/modules/settingmanagement/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/Setting.cs b/modules/settingmanagement/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/Setting.cs
new file mode 100644
index 0000000000..e875004e52
--- /dev/null
+++ b/modules/settingmanagement/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/Setting.cs
@@ -0,0 +1,48 @@
+using System;
+using JetBrains.Annotations;
+using Volo.Abp.Domain.Entities;
+
+namespace Volo.Abp.SettingManagement
+{
+ public class Setting : Entity
+ {
+ [NotNull]
+ public virtual string Name { get; protected set; }
+
+ [NotNull]
+ public virtual string Value { get; internal set; }
+
+ [CanBeNull]
+ public virtual string ProviderName { get; protected set; }
+
+ [CanBeNull]
+ public virtual string ProviderKey { get; protected set; }
+
+ protected Setting()
+ {
+
+ }
+
+ public Setting(
+ Guid id,
+ [NotNull] string name,
+ [NotNull] string value,
+ [CanBeNull] string providerName = null,
+ [CanBeNull] string providerKey = null)
+ {
+ Check.NotNull(name, nameof(name));
+ Check.NotNull(value, nameof(value));
+
+ Id = id;
+ Name = name;
+ Value = value;
+ ProviderName = providerName;
+ ProviderKey = providerKey;
+ }
+
+ public override string ToString()
+ {
+ return $"{base.ToString()}, Name = {Name}, Value = {Value}, ProviderName = {ProviderName}, ProviderKey = {ProviderKey}";
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/settingmanagement/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingStore.cs b/modules/settingmanagement/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingStore.cs
new file mode 100644
index 0000000000..0be50a921c
--- /dev/null
+++ b/modules/settingmanagement/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingStore.cs
@@ -0,0 +1,57 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Guids;
+using Volo.Abp.Settings;
+
+namespace Volo.Abp.SettingManagement
+{
+ public class SettingStore : ISettingStore, ITransientDependency
+ {
+ private readonly ISettingRepository _settingRepository;
+ private readonly IGuidGenerator _guidGenerator;
+
+ public SettingStore(ISettingRepository settingRepository, IGuidGenerator guidGenerator)
+ {
+ _settingRepository = settingRepository;
+ _guidGenerator = guidGenerator;
+ }
+
+ public async Task GetOrNullAsync(string name, string providerName, string providerKey)
+ {
+ var setting = await _settingRepository.FindAsync(name, providerName, providerKey);
+ return setting?.Value;
+ }
+
+ public async Task SetAsync(string name, string value, string providerName, string providerKey)
+ {
+ var setting = await _settingRepository.FindAsync(name, providerName, providerKey);
+ if (setting == null)
+ {
+ setting = new Setting(_guidGenerator.Create(), name, value, providerName, providerKey);
+ await _settingRepository.InsertAsync(setting);
+ }
+ else
+ {
+ setting.Value = value;
+ await _settingRepository.UpdateAsync(setting);
+ }
+ }
+
+ public async Task> GetListAsync(string providerName, string providerKey)
+ {
+ var settings = await _settingRepository.GetListAsync(providerName, providerKey);
+ return settings.Select(s => new SettingValue(s.Name, s.Value)).ToList();
+ }
+
+ public async Task DeleteAsync(string name, string providerName, string providerKey)
+ {
+ var setting = await _settingRepository.FindAsync(name, providerName, providerKey);
+ if (setting != null)
+ {
+ await _settingRepository.DeleteAsync(setting);
+ }
+ }
+ }
+}
diff --git a/modules/settingmanagement/src/Volo.Abp.SettingManagement.EntityFrameworkCore/Volo.Abp.SettingManagement.EntityFrameworkCore.csproj b/modules/settingmanagement/src/Volo.Abp.SettingManagement.EntityFrameworkCore/Volo.Abp.SettingManagement.EntityFrameworkCore.csproj
new file mode 100644
index 0000000000..e56ebc76cd
--- /dev/null
+++ b/modules/settingmanagement/src/Volo.Abp.SettingManagement.EntityFrameworkCore/Volo.Abp.SettingManagement.EntityFrameworkCore.csproj
@@ -0,0 +1,22 @@
+
+
+
+
+
+ netstandard2.0
+ Volo.Abp.SettingManagement.EntityFrameworkCore
+ Volo.Abp.SettingManagement.EntityFrameworkCore
+ $(AssetTargetFallback);portable-net45+win8+wp8+wpa81;
+ false
+ false
+ false
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/settingmanagement/src/Volo.Abp.SettingManagement.EntityFrameworkCore/Volo/Abp/SettingManagement/EntityFrameworkCore/AbpSettingManagementDbContext.cs b/modules/settingmanagement/src/Volo.Abp.SettingManagement.EntityFrameworkCore/Volo/Abp/SettingManagement/EntityFrameworkCore/AbpSettingManagementDbContext.cs
new file mode 100644
index 0000000000..7118aae6fe
--- /dev/null
+++ b/modules/settingmanagement/src/Volo.Abp.SettingManagement.EntityFrameworkCore/Volo/Abp/SettingManagement/EntityFrameworkCore/AbpSettingManagementDbContext.cs
@@ -0,0 +1,29 @@
+using Microsoft.EntityFrameworkCore;
+using Volo.Abp.Data;
+using Volo.Abp.EntityFrameworkCore;
+
+namespace Volo.Abp.SettingManagement.EntityFrameworkCore
+{
+ [ConnectionStringName("AbpSettingManagement")]
+ public class AbpSettingManagementDbContext : AbpDbContext, ISettingManagementDbContext
+ {
+ public static string TablePrefix { get; set; } = AbpSettingManagementConsts.DefaultDbTablePrefix;
+
+ public static string Schema { get; set; } = AbpSettingManagementConsts.DefaultDbSchema;
+
+ public DbSet Settings { get; set; }
+
+ public AbpSettingManagementDbContext(DbContextOptions options)
+ : base(options)
+ {
+
+ }
+
+ protected override void OnModelCreating(ModelBuilder builder)
+ {
+ base.OnModelCreating(builder);
+
+ builder.ConfigureSettingManagement(TablePrefix, Schema);
+ }
+ }
+}
diff --git a/modules/settingmanagement/src/Volo.Abp.SettingManagement.EntityFrameworkCore/Volo/Abp/SettingManagement/EntityFrameworkCore/AbpSettingManagementDbContextModelBuilderExtensions.cs b/modules/settingmanagement/src/Volo.Abp.SettingManagement.EntityFrameworkCore/Volo/Abp/SettingManagement/EntityFrameworkCore/AbpSettingManagementDbContextModelBuilderExtensions.cs
new file mode 100644
index 0000000000..75de647690
--- /dev/null
+++ b/modules/settingmanagement/src/Volo.Abp.SettingManagement.EntityFrameworkCore/Volo/Abp/SettingManagement/EntityFrameworkCore/AbpSettingManagementDbContextModelBuilderExtensions.cs
@@ -0,0 +1,33 @@
+using JetBrains.Annotations;
+using Microsoft.EntityFrameworkCore;
+
+namespace Volo.Abp.SettingManagement.EntityFrameworkCore
+{
+ public static class AbpSettingManagementDbContextModelBuilderExtensions
+ {
+ public static void ConfigureSettingManagement(
+ [NotNull] this ModelBuilder builder,
+ [CanBeNull] string tablePrefix = AbpSettingManagementConsts.DefaultDbTablePrefix,
+ [CanBeNull] string schema = AbpSettingManagementConsts.DefaultDbSchema)
+ {
+ Check.NotNull(builder, nameof(builder));
+
+ if (tablePrefix == null)
+ {
+ tablePrefix = "";
+ }
+
+ builder.Entity(b =>
+ {
+ b.ToTable(tablePrefix + "Settings", schema);
+
+ b.Property(x => x.Name).HasMaxLength(SettingConsts.MaxNameLength).IsRequired();
+ b.Property(x => x.Value).HasMaxLength(SettingConsts.MaxValueLength).IsRequired();
+ b.Property(x => x.ProviderName).HasMaxLength(SettingConsts.MaxProviderNameLength);
+ b.Property(x => x.ProviderKey).HasMaxLength(SettingConsts.MaxProviderKeyLength);
+
+ b.HasIndex(x => new {x.Name, x.ProviderName, x.ProviderKey});
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/settingmanagement/src/Volo.Abp.SettingManagement.EntityFrameworkCore/Volo/Abp/SettingManagement/EntityFrameworkCore/AbpSettingManagementEntityFrameworkCoreModule.cs b/modules/settingmanagement/src/Volo.Abp.SettingManagement.EntityFrameworkCore/Volo/Abp/SettingManagement/EntityFrameworkCore/AbpSettingManagementEntityFrameworkCoreModule.cs
new file mode 100644
index 0000000000..5ec4dd9045
--- /dev/null
+++ b/modules/settingmanagement/src/Volo.Abp.SettingManagement.EntityFrameworkCore/Volo/Abp/SettingManagement/EntityFrameworkCore/AbpSettingManagementEntityFrameworkCoreModule.cs
@@ -0,0 +1,23 @@
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.EntityFrameworkCore;
+using Volo.Abp.Modularity;
+
+namespace Volo.Abp.SettingManagement.EntityFrameworkCore
+{
+ [DependsOn(typeof(AbpSettingManagementDomainModule))]
+ [DependsOn(typeof(AbpEntityFrameworkCoreModule))]
+ public class AbpSettingManagementEntityFrameworkCoreModule : AbpModule
+ {
+ public override void ConfigureServices(IServiceCollection services)
+ {
+ services.AddAbpDbContext(options =>
+ {
+ options.AddDefaultRepositories();
+
+ options.AddRepository();
+ });
+
+ services.AddAssemblyOf();
+ }
+ }
+}
diff --git a/modules/settingmanagement/src/Volo.Abp.SettingManagement.EntityFrameworkCore/Volo/Abp/SettingManagement/EntityFrameworkCore/EfCoreSettingRepository.cs b/modules/settingmanagement/src/Volo.Abp.SettingManagement.EntityFrameworkCore/Volo/Abp/SettingManagement/EntityFrameworkCore/EfCoreSettingRepository.cs
new file mode 100644
index 0000000000..86b31036d1
--- /dev/null
+++ b/modules/settingmanagement/src/Volo.Abp.SettingManagement.EntityFrameworkCore/Volo/Abp/SettingManagement/EntityFrameworkCore/EfCoreSettingRepository.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.EntityFrameworkCore;
+using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
+using Volo.Abp.EntityFrameworkCore;
+
+namespace Volo.Abp.SettingManagement.EntityFrameworkCore
+{
+ public class EfCoreSettingRepository : EfCoreRepository, ISettingRepository
+ {
+ public EfCoreSettingRepository(IDbContextProvider dbContextProvider)
+ : base(dbContextProvider)
+ {
+ }
+
+ public async Task FindAsync(string name, string providerName, string providerKey)
+ {
+ return await DbSet
+ .FirstOrDefaultAsync(
+ s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey
+ );
+ }
+
+ public async Task> GetListAsync(string providerName, string providerKey)
+ {
+ return await DbSet
+ .Where(
+ s => s.ProviderName == providerName && s.ProviderKey == providerKey
+ ).ToListAsync();
+ }
+ }
+}
diff --git a/modules/settingmanagement/src/Volo.Abp.SettingManagement.EntityFrameworkCore/Volo/Abp/SettingManagement/EntityFrameworkCore/ISettingManagementDbContext.cs b/modules/settingmanagement/src/Volo.Abp.SettingManagement.EntityFrameworkCore/Volo/Abp/SettingManagement/EntityFrameworkCore/ISettingManagementDbContext.cs
new file mode 100644
index 0000000000..23763b16d6
--- /dev/null
+++ b/modules/settingmanagement/src/Volo.Abp.SettingManagement.EntityFrameworkCore/Volo/Abp/SettingManagement/EntityFrameworkCore/ISettingManagementDbContext.cs
@@ -0,0 +1,12 @@
+using Microsoft.EntityFrameworkCore;
+using Volo.Abp.Data;
+using Volo.Abp.EntityFrameworkCore;
+
+namespace Volo.Abp.SettingManagement.EntityFrameworkCore
+{
+ [ConnectionStringName("AbpSettingManagement")]
+ public interface ISettingManagementDbContext : IEfCoreDbContext
+ {
+ DbSet Settings { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/modules/settingmanagement/src/Volo.Abp.SettingManagement.MongoDB/Volo.Abp.SettingManagement.MongoDB.csproj b/modules/settingmanagement/src/Volo.Abp.SettingManagement.MongoDB/Volo.Abp.SettingManagement.MongoDB.csproj
new file mode 100644
index 0000000000..d2b9ec7e24
--- /dev/null
+++ b/modules/settingmanagement/src/Volo.Abp.SettingManagement.MongoDB/Volo.Abp.SettingManagement.MongoDB.csproj
@@ -0,0 +1,22 @@
+
+
+
+
+
+ netstandard2.0
+ Volo.Abp.SettingManagement.MongoDB
+ Volo.Abp.SettingManagement.MongoDB
+ $(AssetTargetFallback);portable-net45+win8+wp8+wpa81;
+ false
+ false
+ false
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/settingmanagement/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/AbpSettingManagementBsonClassMap.cs b/modules/settingmanagement/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/AbpSettingManagementBsonClassMap.cs
new file mode 100644
index 0000000000..a816809761
--- /dev/null
+++ b/modules/settingmanagement/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/AbpSettingManagementBsonClassMap.cs
@@ -0,0 +1,21 @@
+using MongoDB.Bson.Serialization;
+using Volo.Abp.Threading;
+
+namespace Volo.Abp.SettingManagement.MongoDB
+{
+ public static class AbpSettingManagementBsonClassMap
+ {
+ private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner();
+
+ public static void Configure()
+ {
+ OneTimeRunner.Run(() =>
+ {
+ BsonClassMap.RegisterClassMap(map =>
+ {
+ map.AutoMap();
+ });
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/settingmanagement/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/AbpSettingManagementMongoDbContextExtensions.cs b/modules/settingmanagement/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/AbpSettingManagementMongoDbContextExtensions.cs
new file mode 100644
index 0000000000..ee7a00d1e2
--- /dev/null
+++ b/modules/settingmanagement/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/AbpSettingManagementMongoDbContextExtensions.cs
@@ -0,0 +1,24 @@
+using System;
+using Volo.Abp.MongoDB;
+
+namespace Volo.Abp.SettingManagement.MongoDB
+{
+ public static class AbpSettingManagementMongoDbContextExtensions
+ {
+ public static void ConfigureSettingManagement(
+ this IMongoModelBuilder builder,
+ Action optionsAction = null)
+ {
+ Check.NotNull(builder, nameof(builder));
+
+ var options = new SettingManagementMongoModelBuilderConfigurationOptions();
+
+ optionsAction?.Invoke(options);
+
+ builder.Entity(b =>
+ {
+ b.CollectionName = options.CollectionPrefix + "Settings";
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/settingmanagement/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/AbpSettingManagementMongoDbModule.cs b/modules/settingmanagement/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/AbpSettingManagementMongoDbModule.cs
new file mode 100644
index 0000000000..3a74663598
--- /dev/null
+++ b/modules/settingmanagement/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/AbpSettingManagementMongoDbModule.cs
@@ -0,0 +1,27 @@
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.Modularity;
+using Volo.Abp.MongoDB;
+
+namespace Volo.Abp.SettingManagement.MongoDB
+{
+ [DependsOn(
+ typeof(AbpSettingManagementDomainModule),
+ typeof(AbpMongoDbModule)
+ )]
+ public class AbpSettingManagementMongoDbModule : AbpModule
+ {
+ public override void ConfigureServices(IServiceCollection services)
+ {
+ AbpSettingManagementBsonClassMap.Configure();
+
+ services.AddMongoDbContext(options =>
+ {
+ options.AddDefaultRepositories();
+
+ options.AddRepository();
+ });
+
+ services.AddAssemblyOf();
+ }
+ }
+}
diff --git a/modules/settingmanagement/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/ISettingManagementMongoDbContext.cs b/modules/settingmanagement/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/ISettingManagementMongoDbContext.cs
new file mode 100644
index 0000000000..2585b92874
--- /dev/null
+++ b/modules/settingmanagement/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/ISettingManagementMongoDbContext.cs
@@ -0,0 +1,12 @@
+using MongoDB.Driver;
+using Volo.Abp.Data;
+using Volo.Abp.MongoDB;
+
+namespace Volo.Abp.SettingManagement.MongoDB
+{
+ [ConnectionStringName("AbpSettingManagement")]
+ public interface ISettingManagementMongoDbContext : IAbpMongoDbContext
+ {
+ IMongoCollection Settings { get; }
+ }
+}
\ No newline at end of file
diff --git a/modules/settingmanagement/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/MongoSettingRepository.cs b/modules/settingmanagement/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/MongoSettingRepository.cs
new file mode 100644
index 0000000000..56516dcbd0
--- /dev/null
+++ b/modules/settingmanagement/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/MongoSettingRepository.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using MongoDB.Driver;
+using MongoDB.Driver.Linq;
+using Volo.Abp.Domain.Repositories.MongoDB;
+using Volo.Abp.MongoDB;
+
+namespace Volo.Abp.SettingManagement.MongoDB
+{
+ public class MongoSettingRepository : MongoDbRepository, ISettingRepository
+ {
+ public MongoSettingRepository(IMongoDbContextProvider dbContextProvider)
+ : base(dbContextProvider)
+ {
+
+ }
+
+ public async Task FindAsync(string name, string providerName, string providerKey)
+ {
+ return await GetMongoQueryable().FirstOrDefaultAsync(s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey);
+ }
+
+ public async Task> GetListAsync(string providerName, string providerKey)
+ {
+ return await GetMongoQueryable().Where(s => s.ProviderName == providerName && s.ProviderKey == providerKey).ToListAsync();
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/settingmanagement/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/SettingManagementMongoDbContext.cs b/modules/settingmanagement/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/SettingManagementMongoDbContext.cs
new file mode 100644
index 0000000000..1917a79fc5
--- /dev/null
+++ b/modules/settingmanagement/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/SettingManagementMongoDbContext.cs
@@ -0,0 +1,24 @@
+using MongoDB.Driver;
+using Volo.Abp.Data;
+using Volo.Abp.MongoDB;
+
+namespace Volo.Abp.SettingManagement.MongoDB
+{
+ [ConnectionStringName("AbpSettingManagement")]
+ public class SettingManagementMongoDbContext : AbpMongoDbContext, ISettingManagementMongoDbContext
+ {
+ public static string CollectionPrefix { get; set; } = AbpSettingManagementConsts.DefaultDbTablePrefix;
+
+ public IMongoCollection Settings => Collection();
+
+ protected override void CreateModel(IMongoModelBuilder modelBuilder)
+ {
+ base.CreateModel(modelBuilder);
+
+ modelBuilder.ConfigureSettingManagement(options =>
+ {
+ options.CollectionPrefix = CollectionPrefix;
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/settingmanagement/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/SettingManagementMongoModelBuilderConfigurationOptions.cs b/modules/settingmanagement/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/SettingManagementMongoModelBuilderConfigurationOptions.cs
new file mode 100644
index 0000000000..aad41fc470
--- /dev/null
+++ b/modules/settingmanagement/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/SettingManagementMongoModelBuilderConfigurationOptions.cs
@@ -0,0 +1,13 @@
+using JetBrains.Annotations;
+using Volo.Abp.MongoDB;
+
+namespace Volo.Abp.SettingManagement.MongoDB
+{
+ public class SettingManagementMongoModelBuilderConfigurationOptions : MongoModelBuilderConfigurationOptions
+ {
+ public SettingManagementMongoModelBuilderConfigurationOptions([NotNull] string tablePrefix = AbpSettingManagementConsts.DefaultDbTablePrefix)
+ : base(tablePrefix)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/settingmanagement/test/Volo.Abp.SettingManagement.EntityFrameworkCore.Tests/Volo.Abp.SettingManagement.EntityFrameworkCore.Tests.csproj b/modules/settingmanagement/test/Volo.Abp.SettingManagement.EntityFrameworkCore.Tests/Volo.Abp.SettingManagement.EntityFrameworkCore.Tests.csproj
new file mode 100644
index 0000000000..fff9df515e
--- /dev/null
+++ b/modules/settingmanagement/test/Volo.Abp.SettingManagement.EntityFrameworkCore.Tests/Volo.Abp.SettingManagement.EntityFrameworkCore.Tests.csproj
@@ -0,0 +1,25 @@
+
+
+
+ netcoreapp2.0
+ Volo.Abp.SettingManagement.EntityFrameworkCore.Tests
+ Volo.Abp.SettingManagement.EntityFrameworkCore.Tests
+ true
+ false
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/settingmanagement/test/Volo.Abp.SettingManagement.EntityFrameworkCore.Tests/Volo/Abp/SettingManagement/EntityFrameworkCore/AbpSettingManagementEntityFrameworkCoreTestModule.cs b/modules/settingmanagement/test/Volo.Abp.SettingManagement.EntityFrameworkCore.Tests/Volo/Abp/SettingManagement/EntityFrameworkCore/AbpSettingManagementEntityFrameworkCoreTestModule.cs
new file mode 100644
index 0000000000..1bc2ae5fdd
--- /dev/null
+++ b/modules/settingmanagement/test/Volo.Abp.SettingManagement.EntityFrameworkCore.Tests/Volo/Abp/SettingManagement/EntityFrameworkCore/AbpSettingManagementEntityFrameworkCoreTestModule.cs
@@ -0,0 +1,44 @@
+using Microsoft.Data.Sqlite;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Storage;
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.EntityFrameworkCore;
+using Volo.Abp.Modularity;
+
+namespace Volo.Abp.SettingManagement.EntityFrameworkCore
+{
+ [DependsOn(
+ typeof(AbpSettingManagementTestBaseModule),
+ typeof(AbpSettingManagementEntityFrameworkCoreModule)
+ )]
+ public class AbpSettingManagementEntityFrameworkCoreTestModule : AbpModule
+ {
+ public override void ConfigureServices(IServiceCollection services)
+ {
+ var sqliteConnection = CreateDatabaseAndGetConnection();
+
+ services.Configure(options =>
+ {
+ options.Configure(context =>
+ {
+ context.DbContextOptions.UseSqlite(sqliteConnection);
+ });
+ });
+
+ services.AddAssemblyOf();
+ }
+
+ private static SqliteConnection CreateDatabaseAndGetConnection()
+ {
+ var connection = new SqliteConnection("Data Source=:memory:");
+ connection.Open();
+
+ new AbpSettingManagementDbContext(
+ new DbContextOptionsBuilder().UseSqlite(connection).Options
+ ).GetService().CreateTables();
+
+ return connection;
+ }
+ }
+}
diff --git a/modules/settingmanagement/test/Volo.Abp.SettingManagement.EntityFrameworkCore.Tests/Volo/Abp/SettingManagement/EntityFrameworkCore/SettingRepository_Tests.cs b/modules/settingmanagement/test/Volo.Abp.SettingManagement.EntityFrameworkCore.Tests/Volo/Abp/SettingManagement/EntityFrameworkCore/SettingRepository_Tests.cs
new file mode 100644
index 0000000000..19ceb328a6
--- /dev/null
+++ b/modules/settingmanagement/test/Volo.Abp.SettingManagement.EntityFrameworkCore.Tests/Volo/Abp/SettingManagement/EntityFrameworkCore/SettingRepository_Tests.cs
@@ -0,0 +1,7 @@
+namespace Volo.Abp.SettingManagement.EntityFrameworkCore
+{
+ public class SettingRepository_Tests : SettingRepository_Tests
+ {
+
+ }
+}
diff --git a/modules/settingmanagement/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo.Abp.SettingManagement.MongoDB.Tests.csproj b/modules/settingmanagement/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo.Abp.SettingManagement.MongoDB.Tests.csproj
new file mode 100644
index 0000000000..88472345bd
--- /dev/null
+++ b/modules/settingmanagement/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo.Abp.SettingManagement.MongoDB.Tests.csproj
@@ -0,0 +1,24 @@
+
+
+
+ netcoreapp2.0
+ Volo.Abp.SettingManagement.MongoDB.Tests
+ Volo.Abp.SettingManagement.MongoDB.Tests
+ true
+ false
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/settingmanagement/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo/Abp/SettingManagement/MongoDB/AbpSettingManagementMongoDbTestModule.cs b/modules/settingmanagement/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo/Abp/SettingManagement/MongoDB/AbpSettingManagementMongoDbTestModule.cs
new file mode 100644
index 0000000000..c3e4c177aa
--- /dev/null
+++ b/modules/settingmanagement/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo/Abp/SettingManagement/MongoDB/AbpSettingManagementMongoDbTestModule.cs
@@ -0,0 +1,33 @@
+using Microsoft.Extensions.DependencyInjection;
+using Mongo2Go;
+using Volo.Abp.Data;
+using Volo.Abp.Modularity;
+
+namespace Volo.Abp.SettingManagement.MongoDB
+{
+ [DependsOn(
+ typeof(AbpSettingManagementMongoDbModule),
+ typeof(AbpSettingManagementTestBaseModule)
+ )]
+ public class AbpSettingManagementMongoDbTestModule : AbpModule
+ {
+ private MongoDbRunner _mongoDbRunner;
+
+ public override void ConfigureServices(IServiceCollection services)
+ {
+ _mongoDbRunner = MongoDbRunner.Start();
+
+ services.Configure(options =>
+ {
+ options.ConnectionStrings.Default = _mongoDbRunner.ConnectionString;
+ });
+
+ services.AddAssemblyOf();
+ }
+
+ public override void OnApplicationShutdown(ApplicationShutdownContext context)
+ {
+ _mongoDbRunner.Dispose();
+ }
+ }
+}
diff --git a/modules/settingmanagement/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo/Abp/SettingManagement/MongoDB/SettingRepository_Tests.cs b/modules/settingmanagement/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo/Abp/SettingManagement/MongoDB/SettingRepository_Tests.cs
new file mode 100644
index 0000000000..7e35eff799
--- /dev/null
+++ b/modules/settingmanagement/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo/Abp/SettingManagement/MongoDB/SettingRepository_Tests.cs
@@ -0,0 +1,7 @@
+namespace Volo.Abp.SettingManagement.MongoDB
+{
+ public class SettingRepository_Tests : SettingRepository_Tests
+ {
+
+ }
+}
diff --git a/modules/settingmanagement/test/Volo.Abp.SettingManagement.TestBase/Volo.Abp.SettingManagement.TestBase.csproj b/modules/settingmanagement/test/Volo.Abp.SettingManagement.TestBase/Volo.Abp.SettingManagement.TestBase.csproj
new file mode 100644
index 0000000000..497395eb4a
--- /dev/null
+++ b/modules/settingmanagement/test/Volo.Abp.SettingManagement.TestBase/Volo.Abp.SettingManagement.TestBase.csproj
@@ -0,0 +1,29 @@
+
+
+
+ netcoreapp2.0
+ Volo.Abp.SettingManagement.TestBase
+ Volo.Abp.SettingManagement.TestBase
+ true
+ false
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/settingmanagement/test/Volo.Abp.SettingManagement.TestBase/Volo/Abp/SettingManagement/AbpSettingManagementTestBaseModule.cs b/modules/settingmanagement/test/Volo.Abp.SettingManagement.TestBase/Volo/Abp/SettingManagement/AbpSettingManagementTestBaseModule.cs
new file mode 100644
index 0000000000..53c66d29e0
--- /dev/null
+++ b/modules/settingmanagement/test/Volo.Abp.SettingManagement.TestBase/Volo/Abp/SettingManagement/AbpSettingManagementTestBaseModule.cs
@@ -0,0 +1,39 @@
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.Autofac;
+using Volo.Abp.Modularity;
+using Volo.Abp.Settings;
+
+namespace Volo.Abp.SettingManagement
+{
+ [DependsOn(
+ typeof(AbpAutofacModule),
+ typeof(AbpTestBaseModule),
+ typeof(AbpSettingManagementDomainModule))]
+ public class AbpSettingManagementTestBaseModule : AbpModule
+ {
+ public override void ConfigureServices(IServiceCollection services)
+ {
+ services.Configure(options =>
+ {
+ options.DefinitionProviders.Add();
+ });
+
+ services.AddAssemblyOf();
+ }
+
+ public override void OnApplicationInitialization(ApplicationInitializationContext context)
+ {
+ SeedTestData(context);
+ }
+
+ private static void SeedTestData(ApplicationInitializationContext context)
+ {
+ using (var scope = context.ServiceProvider.CreateScope())
+ {
+ scope.ServiceProvider
+ .GetRequiredService()
+ .Build();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/settingmanagement/test/Volo.Abp.SettingManagement.TestBase/Volo/Abp/SettingManagement/SettingManagementTestBase.cs b/modules/settingmanagement/test/Volo.Abp.SettingManagement.TestBase/Volo/Abp/SettingManagement/SettingManagementTestBase.cs
new file mode 100644
index 0000000000..c6deeba0fc
--- /dev/null
+++ b/modules/settingmanagement/test/Volo.Abp.SettingManagement.TestBase/Volo/Abp/SettingManagement/SettingManagementTestBase.cs
@@ -0,0 +1,13 @@
+using Volo.Abp.Modularity;
+
+namespace Volo.Abp.SettingManagement
+{
+ public class SettingManagementTestBase : AbpIntegratedTest
+ where TStartupModule : IAbpModule
+ {
+ protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
+ {
+ options.UseAutofac();
+ }
+ }
+}
diff --git a/modules/settingmanagement/test/Volo.Abp.SettingManagement.TestBase/Volo/Abp/SettingManagement/SettingRepository_Tests.cs b/modules/settingmanagement/test/Volo.Abp.SettingManagement.TestBase/Volo/Abp/SettingManagement/SettingRepository_Tests.cs
new file mode 100644
index 0000000000..ea52e4458c
--- /dev/null
+++ b/modules/settingmanagement/test/Volo.Abp.SettingManagement.TestBase/Volo/Abp/SettingManagement/SettingRepository_Tests.cs
@@ -0,0 +1,53 @@
+using System.Linq;
+using System.Threading.Tasks;
+using Shouldly;
+using Volo.Abp.Modularity;
+using Volo.Abp.Settings;
+using Xunit;
+
+namespace Volo.Abp.SettingManagement
+{
+ public abstract class SettingRepository_Tests : SettingManagementTestBase
+ where TStartupModule : IAbpModule
+ {
+ protected ISettingRepository SettingRepository { get; }
+ protected SettingTestData TestData { get; }
+
+ protected SettingRepository_Tests()
+ {
+ SettingRepository = GetRequiredService();
+ TestData = GetRequiredService();
+ }
+
+ [Fact]
+ public async Task FindAsync()
+ {
+ (await SettingRepository.FindAsync(
+ "MySetting1",
+ GlobalSettingValueProvider.ProviderName,
+ null
+ )).Value.ShouldBe("42");
+
+ (await SettingRepository.FindAsync(
+ "MySetting2",
+ "User",
+ TestData.User1Id.ToString()
+ )).Value.ShouldBe("user1-store-value");
+
+ (await SettingRepository.FindAsync(
+ "Undefined-Setting",
+ GlobalSettingValueProvider.ProviderName,
+ null
+ )).ShouldBeNull();
+ }
+
+ [Fact]
+ public async Task GetListAsync()
+ {
+ var settings = await SettingRepository.GetListAsync(GlobalSettingValueProvider.ProviderName, null);
+ settings.Any().ShouldBeTrue();
+ settings.ShouldContain(s => s.Name == "MySetting1" && s.Value == "42");
+ settings.ShouldContain(s => s.Name == "MySetting2" && s.Value == "default-store-value");
+ }
+ }
+}
diff --git a/modules/settingmanagement/test/Volo.Abp.SettingManagement.TestBase/Volo/Abp/SettingManagement/SettingTestData.cs b/modules/settingmanagement/test/Volo.Abp.SettingManagement.TestBase/Volo/Abp/SettingManagement/SettingTestData.cs
new file mode 100644
index 0000000000..066ec4c45d
--- /dev/null
+++ b/modules/settingmanagement/test/Volo.Abp.SettingManagement.TestBase/Volo/Abp/SettingManagement/SettingTestData.cs
@@ -0,0 +1,11 @@
+using System;
+using Volo.Abp.DependencyInjection;
+
+namespace Volo.Abp.SettingManagement
+{
+ public class SettingTestData : ISingletonDependency
+ {
+ public Guid User1Id { get; } = Guid.NewGuid();
+ public Guid User2Id { get; } = Guid.NewGuid();
+ }
+}
\ No newline at end of file
diff --git a/modules/settingmanagement/test/Volo.Abp.SettingManagement.TestBase/Volo/Abp/SettingManagement/SettingTestDataBuilder.cs b/modules/settingmanagement/test/Volo.Abp.SettingManagement.TestBase/Volo/Abp/SettingManagement/SettingTestDataBuilder.cs
new file mode 100644
index 0000000000..ce0a71b6db
--- /dev/null
+++ b/modules/settingmanagement/test/Volo.Abp.SettingManagement.TestBase/Volo/Abp/SettingManagement/SettingTestDataBuilder.cs
@@ -0,0 +1,83 @@
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Guids;
+using Volo.Abp.Settings;
+
+namespace Volo.Abp.SettingManagement
+{
+ public class SettingTestDataBuilder : ITransientDependency
+ {
+ private readonly ISettingRepository _settingRepository;
+ private readonly IGuidGenerator _guidGenerator;
+ private readonly SettingTestData _testData;
+
+ public SettingTestDataBuilder(
+ ISettingRepository settingRepository,
+ IGuidGenerator guidGenerator,
+ SettingTestData testData)
+ {
+ _settingRepository = settingRepository;
+ _guidGenerator = guidGenerator;
+ _testData = testData;
+ }
+
+ public void Build()
+ {
+ _settingRepository.InsertAsync(
+ new Setting(
+ _guidGenerator.Create(),
+ "MySetting1",
+ "42",
+ GlobalSettingValueProvider.ProviderName
+ )
+ );
+
+ _settingRepository.InsertAsync(
+ new Setting(
+ _guidGenerator.Create(),
+ "MySetting2",
+ "default-store-value",
+ GlobalSettingValueProvider.ProviderName
+ )
+ );
+
+ _settingRepository.InsertAsync(
+ new Setting(
+ _guidGenerator.Create(),
+ "MySetting2",
+ "user1-store-value",
+ "User",
+ _testData.User1Id.ToString()
+ )
+ );
+
+ _settingRepository.InsertAsync(
+ new Setting(
+ _guidGenerator.Create(),
+ "MySetting2",
+ "user2-store-value",
+ "User",
+ _testData.User2Id.ToString()
+ )
+ );
+
+ _settingRepository.InsertAsync(
+ new Setting(
+ _guidGenerator.Create(),
+ "MySettingWithoutInherit",
+ "default-store-value",
+ GlobalSettingValueProvider.ProviderName
+ )
+ );
+
+ _settingRepository.InsertAsync(
+ new Setting(
+ _guidGenerator.Create(),
+ "MySettingWithoutInherit",
+ "user1-store-value",
+ "User",
+ _testData.User1Id.ToString()
+ )
+ );
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/settingmanagement/test/Volo.Abp.SettingManagement.TestBase/Volo/Abp/SettingManagement/TestSettingDefinitionProvider.cs b/modules/settingmanagement/test/Volo.Abp.SettingManagement.TestBase/Volo/Abp/SettingManagement/TestSettingDefinitionProvider.cs
new file mode 100644
index 0000000000..2bf4a628da
--- /dev/null
+++ b/modules/settingmanagement/test/Volo.Abp.SettingManagement.TestBase/Volo/Abp/SettingManagement/TestSettingDefinitionProvider.cs
@@ -0,0 +1,15 @@
+using Volo.Abp.Settings;
+
+namespace Volo.Abp.SettingManagement
+{
+ public class TestSettingDefinitionProvider : SettingDefinitionProvider
+ {
+ public override void Define(ISettingDefinitionContext context)
+ {
+ context.Add(new SettingDefinition("MySetting1"));
+ context.Add(new SettingDefinition("MySetting2"));
+ context.Add(new SettingDefinition("MySettingWithoutInherit", isInherited: false));
+ context.Add(new SettingDefinition("SettingNotSetInStore", defaultValue: "default-value"));
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/settingmanagement/test/Volo.Abp.SettingManagement.Tests/Volo.Abp.SettingManagement.Tests.csproj b/modules/settingmanagement/test/Volo.Abp.SettingManagement.Tests/Volo.Abp.SettingManagement.Tests.csproj
new file mode 100644
index 0000000000..7045788aa6
--- /dev/null
+++ b/modules/settingmanagement/test/Volo.Abp.SettingManagement.Tests/Volo.Abp.SettingManagement.Tests.csproj
@@ -0,0 +1,25 @@
+
+
+
+ netcoreapp2.0
+ Volo.Abp.SettingManagement.Tests
+ Volo.Abp.SettingManagement.Tests
+ true
+ false
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/settingmanagement/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/AbpSettingManagementTestModule.cs b/modules/settingmanagement/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/AbpSettingManagementTestModule.cs
new file mode 100644
index 0000000000..d4360849a3
--- /dev/null
+++ b/modules/settingmanagement/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/AbpSettingManagementTestModule.cs
@@ -0,0 +1,18 @@
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.Modularity;
+using Volo.Abp.SettingManagement.EntityFrameworkCore;
+using Volo.Abp.Users;
+
+namespace Volo.Abp.SettingManagement
+{
+ [DependsOn(
+ typeof(AbpSettingManagementEntityFrameworkCoreTestModule),
+ typeof(AbpUsersAbstractionModule))]
+ public class AbpSettingManagementTestModule : AbpModule //TODO: Rename to Volo.Abp.SettingManagement.Domain.Tests..?
+ {
+ public override void ConfigureServices(IServiceCollection services)
+ {
+ services.AddAssemblyOf();
+ }
+ }
+}
diff --git a/modules/settingmanagement/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingManager_Basic_Tests.cs b/modules/settingmanagement/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingManager_Basic_Tests.cs
new file mode 100644
index 0000000000..0e9543cc96
--- /dev/null
+++ b/modules/settingmanagement/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingManager_Basic_Tests.cs
@@ -0,0 +1,56 @@
+using System.Threading.Tasks;
+using Shouldly;
+using Volo.Abp.Settings;
+using Xunit;
+
+namespace Volo.Abp.SettingManagement
+{
+ public class SettingManager_Basic_Tests : SettingsTestBase
+ {
+ private readonly ISettingManager _settingManager;
+
+ public SettingManager_Basic_Tests()
+ {
+ _settingManager = GetRequiredService();
+ }
+
+ [Fact]
+ public async Task Should_Throw_Exception_When_Try_To_Get_An_Undefined_Setting()
+ {
+ await Assert.ThrowsAsync(
+ async () => await _settingManager.GetOrNullAsync("UndefinedSetting")
+ );
+ }
+
+ [Fact]
+ public async Task Should_Get_Default_Value_If_Not_Set_In_Store()
+ {
+ var value = await _settingManager.GetOrNullAsync("SettingNotSetInStore");
+ value.ShouldBe("default-value");
+ }
+
+ [Fact]
+ public async Task Should_Get_Base_Store_Value()
+ {
+ (await _settingManager.GetOrNullAsync("MySetting1")).ShouldBe("42");
+ }
+
+ [Fact]
+ public async Task Should_Get_All_Base_Store_Values()
+ {
+ var settingValues = await _settingManager.GetAllAsync();
+ settingValues.ShouldContain(sv => sv.Name == "MySetting1" && sv.Value == "42");
+ settingValues.ShouldContain(sv => sv.Name == "MySetting2" && sv.Value == "default-store-value");
+ settingValues.ShouldContain(sv => sv.Name == "SettingNotSetInStore" && sv.Value == "default-value");
+ }
+
+ [Fact]
+ public async Task Should_Set_Global_Value()
+ {
+ await _settingManager.SetGlobalAsync("MySetting1", "43");
+
+ (await _settingManager.GetOrNullGlobalAsync("MySetting1")).ShouldBe("43");
+ (await _settingManager.GetOrNullAsync("MySetting1")).ShouldBe("43");
+ }
+ }
+}
diff --git a/modules/settingmanagement/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingManager_User_Tests.cs b/modules/settingmanagement/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingManager_User_Tests.cs
new file mode 100644
index 0000000000..90fff7e640
--- /dev/null
+++ b/modules/settingmanagement/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingManager_User_Tests.cs
@@ -0,0 +1,188 @@
+using System;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.Extensions.DependencyInjection;
+using NSubstitute;
+using Shouldly;
+using Volo.Abp.Settings;
+using Volo.Abp.Users;
+using Xunit;
+
+namespace Volo.Abp.SettingManagement
+{
+ public class SettingManager_User_Tests: SettingsTestBase
+ {
+ private Guid? _currentUserId;
+
+ private readonly ISettingManager _settingManager;
+ private readonly SettingTestData _testData;
+
+ public SettingManager_User_Tests()
+ {
+ _settingManager = GetRequiredService();
+ _testData = GetRequiredService();
+ }
+
+ protected override void AfterAddApplication(IServiceCollection services)
+ {
+ var currentUser = Substitute.For();
+ currentUser.Id.Returns(ci => _currentUserId);
+ services.AddSingleton(currentUser);
+ }
+
+ [Fact]
+ public async Task Should_Get_From_Store_For_Given_User()
+ {
+ (await _settingManager.GetOrNullForUserAsync("MySetting2", _testData.User1Id)).ShouldBe("user1-store-value");
+ (await _settingManager.GetOrNullForUserAsync("MySetting2", _testData.User2Id)).ShouldBe("user2-store-value");
+ }
+
+ [Fact]
+ public async Task Should_Fallback_To_Default_Store_Value_When_No_Value_For_Given_User()
+ {
+ (await _settingManager.GetOrNullForUserAsync("MySetting2", Guid.NewGuid())).ShouldBe("default-store-value");
+ }
+
+ [Fact]
+ public async Task Should_Not_Fallback_To_Default_Store_Value_When_No_Value_For_Given_User_But_Specified_Fallback_As_False()
+ {
+ (await _settingManager.GetOrNullForUserAsync("MySetting2", Guid.NewGuid(), fallback: false)).ShouldBeNull();
+ }
+
+ [Fact]
+ public async Task Should_Get_From_Store_For_Current_User()
+ {
+ _currentUserId = _testData.User1Id;
+ (await _settingManager.GetOrNullAsync("MySetting2")).ShouldBe("user1-store-value");
+
+ _currentUserId = _testData.User2Id;
+ (await _settingManager.GetOrNullAsync("MySetting2")).ShouldBe("user2-store-value");
+ }
+
+ [Fact]
+ public async Task Should_Fallback_To_Default_Store_Value_When_No_Value_For_Current_User()
+ {
+ _currentUserId = Guid.NewGuid();
+ (await _settingManager.GetOrNullAsync("MySetting2")).ShouldBe("default-store-value");
+ }
+
+ [Fact]
+ public async Task Should_Get_From_Store_For_Current_User_With_GetOrNullForCurrentUserAsync()
+ {
+ _currentUserId = _testData.User1Id;
+ (await _settingManager.GetOrNullForCurrentUserAsync("MySetting2")).ShouldBe("user1-store-value");
+
+ _currentUserId = _testData.User2Id;
+ (await _settingManager.GetOrNullForCurrentUserAsync("MySetting2")).ShouldBe("user2-store-value");
+ }
+
+ [Fact]
+ public async Task Should_Fallback_To_Default_Store_Value_When_No_Value_For_Current_User_With_GetOrNullForCurrentUserAsync()
+ {
+ _currentUserId = Guid.NewGuid();
+ (await _settingManager.GetOrNullAsync("MySetting2")).ShouldBe("default-store-value");
+ }
+
+ [Fact]
+ public async Task Should_Not_Fallback_To_Default_Store_Value_When_No_Value_For_Current_User_But_Specified_Fallback_As_False()
+ {
+ _currentUserId = Guid.NewGuid();
+ (await _settingManager.GetOrNullForCurrentUserAsync("MySetting2", fallback: false)).ShouldBeNull();
+ }
+
+ [Fact]
+ public async Task Should_Get_All_From_Store_For_Given_User()
+ {
+ var settingValues = await _settingManager.GetAllForUserAsync(_testData.User1Id);
+ settingValues.ShouldContain(sv => sv.Name == "MySetting1" && sv.Value == "42");
+ settingValues.ShouldContain(sv => sv.Name == "MySetting2" && sv.Value == "user1-store-value");
+ settingValues.ShouldContain(sv => sv.Name == "SettingNotSetInStore" && sv.Value == "default-value");
+ }
+
+ [Fact]
+ public async Task Should_Get_All_From_Store_For_Given_User_Without_Fallback()
+ {
+ var settingValues = await _settingManager.GetAllForUserAsync(_testData.User1Id, fallback: false);
+ settingValues.ShouldContain(sv => sv.Name == "MySetting2" && sv.Value == "user1-store-value");
+ settingValues.ShouldContain(sv => sv.Name == "MySettingWithoutInherit" && sv.Value == "user1-store-value");
+ settingValues.ShouldNotContain(sv => sv.Name == "MySetting1");
+ }
+
+ [Fact]
+ public async Task Should_Delete_Setting_Record_When_Set_To_Null()
+ {
+ await _settingManager.SetForUserAsync(_testData.User1Id, "MySetting2", null);
+
+ GetSettingsFromDbContext(
+ UserSettingValueProvider.ProviderName,
+ _testData.User1Id.ToString(),
+ "MySetting2"
+ ).Count.ShouldBe(0);
+ }
+
+ [Fact]
+ public async Task Should_Change_User_Setting()
+ {
+ (await _settingManager.GetOrNullForUserAsync("MySetting2", _testData.User1Id))
+ .ShouldBe("user1-store-value");
+
+ await _settingManager.SetForUserAsync(_testData.User1Id, "MySetting2", "user1-new-store-value");
+
+ (await _settingManager.GetOrNullForUserAsync("MySetting2", _testData.User1Id))
+ .ShouldBe("user1-new-store-value");
+
+ GetSettingsFromDbContext(
+ UserSettingValueProvider.ProviderName,
+ _testData.User1Id.ToString(),
+ "MySetting2"
+ ).Single().Value.ShouldBe("user1-new-store-value");
+ }
+
+ [Fact]
+ public async Task Should_Delete_Setting_Record_When_Set_To_Fallback_Value()
+ {
+ await _settingManager.SetForUserAsync(
+ _testData.User1Id,
+ "MySetting2",
+ "default-store-value"
+ );
+
+ GetSettingsFromDbContext(
+ UserSettingValueProvider.ProviderName,
+ _testData.User1Id.ToString(),
+ "MySetting2"
+ ).Count.ShouldBe(0);
+
+ (await _settingManager.GetOrNullForUserAsync("MySetting2", _testData.User1Id))
+ .ShouldBe("default-store-value");
+ }
+
+ [Fact]
+ public async Task Should_Not_Delete_Setting_Record_When_Set_To_Fallback_Value_If_Forced()
+ {
+ await _settingManager.SetForUserAsync(
+ _testData.User1Id,
+ "MySetting2",
+ "default-store-value",
+ forceToSet: true
+ );
+
+ GetSettingsFromDbContext(
+ UserSettingValueProvider.ProviderName,
+ _testData.User1Id.ToString(),
+ "MySetting2"
+ ).Single().Value.ShouldBe("default-store-value");
+
+ (await _settingManager.GetOrNullForUserAsync("MySetting2", _testData.User1Id))
+ .ShouldBe("default-store-value");
+ }
+
+ [Fact]
+ public async Task Should_Get_For_Given_User_For_Non_Inherited_Setting()
+ {
+ (await _settingManager.GetOrNullForUserAsync("MySettingWithoutInherit", _testData.User1Id)).ShouldBe("user1-store-value");
+ (await _settingManager.GetOrNullForUserAsync("MySettingWithoutInherit", _testData.User2Id)).ShouldBeNull(); //Does not inherit!
+ (await _settingManager.GetOrNullGlobalAsync("MySettingWithoutInherit")).ShouldBe("default-store-value");
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/settingmanagement/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingsTestBase.cs b/modules/settingmanagement/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingsTestBase.cs
new file mode 100644
index 0000000000..2e0721bbbc
--- /dev/null
+++ b/modules/settingmanagement/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingsTestBase.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Volo.Abp.SettingManagement.EntityFrameworkCore;
+
+namespace Volo.Abp.SettingManagement
+{
+ public class SettingsTestBase : SettingManagementTestBase
+ {
+ protected virtual void UsingDbContext(Action action)
+ {
+ using (var dbContext = GetRequiredService())
+ {
+ action.Invoke(dbContext);
+ }
+ }
+
+ protected virtual T UsingDbContext(Func action)
+ {
+ using (var dbContext = GetRequiredService())
+ {
+ return action.Invoke(dbContext);
+ }
+ }
+
+ protected List GetSettingsFromDbContext(string entityType, string entityId, string name)
+ {
+ return UsingDbContext(context =>
+ context.Settings.Where(
+ s =>
+ s.ProviderName == entityType &&
+ s.ProviderKey == entityId &&
+ s.Name == name
+ ).ToList()
+ );
+ }
+ }
+}