[英]Using IOptions and load options from database with multi tenant application
我将应用程序移动到 .net 核心并尝试使用 IOptions 模式。
我的应用程序是具有单个数据库的多租户。 系统具有全局默认选项,我将它们保存在数据库中(与我的旧应用程序相同),并且每个租户都有自己的选项。 如果租户没有全局键的选项,那么我需要使用全局选项。
在配置中,我处理从数据库中获取全局选项。 文档中的示例很容易。
然而,每个租户的选择并不顺利。 虽然我实际上知道我想要什么,但我不知道如何在 .Net Core 中做到这一点。
我在控制台应用程序中进行测试。
class Program {
static void Main(string[] args) {
var services = ConfigureServices();
var serviceProvider = services.BuildServiceProvider();
serviceProvider.GetService<App>().Run();
}
public class App {
private readonly IOptionsSnapshot<DemoOptions> _options;
public App(IOptionsSnapshot<DemoOptions> options) {
_options = options;
}
public void Run() {
Console.WriteLine("Hello from App.cs");
Console.WriteLine($"DemoOptions:Global:Enabled={_options.Value.Enabled}");
Console.WriteLine($"DemoOptions:Global:AutoRetryDelay={_options.Value.AutoRetryDelay}");
Console.WriteLine($"DemoOptions:Global:IdentityOptions:MaxUserNameLength={_options.Value.IdentityOptions.MaxUserNameLength}");
}
}
private static IServiceCollection ConfigureServices() {
IServiceCollection services = new ServiceCollection();
//Load global configuration from database and use them.
var config = LoadConfiguration();
services.AddSingleton(config);
services.AddDbContext<EntityConfigurationContext>(options => options.UseInMemoryDatabase("InMemoryDb"));
services.AddScoped<ITenantService, TenantService>();
//I take this part from example link in below. But I am not successed.
services.AddSingleton<IOptionsMonitorCache<DemoOptions>,TenantOptionsCache<DemoOptions>>();
services.AddTransient<IOptionsFactory<DemoOptions>,TenantOptionsFactory<DemoOptions>>();
services.AddScoped<IOptionsSnapshot<DemoOptions>,TenantOptions<DemoOptions>>();
services.AddSingleton<IOptions<DemoOptions>,TenantOptions<DemoOptions>>();
// required to run the application
services.AddTransient<App>();
return services;
}
public static IConfiguration LoadConfiguration() {
var builder = new ConfigurationBuilder();
builder.Sources.Clear();
builder.AddEntityConfiguration(options => options.UseInMemoryDatabase("InMemoryDb"));
IConfigurationRoot configurationRoot = builder.Build();
DemoOptions options = new();
configurationRoot.GetSection($"{nameof(DemoOptions)}:{DemoOptions.Global}").Bind(options);
Console.WriteLine($"DemoOptions:Global:Enabled={options.Enabled}");
Console.WriteLine($"DemoOptions:Global:AutoRetryDelay={options.AutoRetryDelay}");
Console.WriteLine($"DemoOptions:Global:IdentityOptions:MaxUserNameLength={options.IdentityOptions.MaxUserNameLength}");
return builder.Build();
}
}
public record DemoOptions {
public const string Global = nameof(Global);
public const string Tenant = nameof(Tenant);
public bool Enabled { get; set; }
public TimeSpan AutoRetryDelay { get; set; }
public IdentityOptions IdentityOptions { get; set; }
}
public record IdentityOptions {
public int MaxUserNameLength { get; set; }
}
public record DemoSettings(string Key, string Value) {
public int Id { get; set; }
}
public record TenantSettings(string Key, string Value, int TenantId) {
public int Id { get; set; }
}
我懂了。 你应该做这些事情
Microsoft.Extensions.Options.ConfigurationExtensions
var config = LoadConfiguration();
services.Configure<DemoOptions>(config.GetSection($"{nameof(DemoOptions)}:{DemoOptions.Global}"));
services.AddSingleton(config);
您可以尝试现成的JsonRepositoryConfiguration Nuget package。 它还具有自动刷新功能,其工作方式与 JSON 配置文件的配置形式非常相似,只是它需要来自您的存储库的 JSON 配置,这反过来可以从任何内部/外部存储中获取数据,包括进行数据库调用,ZDB974238708CA 等.
您可以混合使用不同的配置提供(例如这个和 JSON 配置文件)并根据需要一起使用它们。 忏悔:我是作者。
下一步将使用Named Options 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.