在ASP.NET Core上实施每个租户策略的数据库

不定时更新翻译系列,此系列更新毫无时间规律,文笔菜翻译菜求各位看官老爷们轻喷,如觉得我翻译有问题请挪步原博客地址

本博文翻译自:

http://gunnarpeipman.com/2017/08/database-per-tenant/

让我们继续使用ASP.NET Core web应用程序中的多租户,并关注每个租户都有自己的数据库的解决方案。它不仅仅是关于数据库的——可以有更多的服务,每个租户都有自己的实例。它使这里提供的解决方案可以轻松地扩展到除SQL Server或其他任何关系数据库之外的其他服务。

以往的工作

在讨论解决方案之前,我建议先浏览一下我以前的文章,内容包括ASP.NET Core web应用程序中的多租户的一些方面:

注意! 本文中的代码建立在上述文章的代码之上。

将数据库连接字符串移动到租户配置

这里的问题是如何动态决定使用哪个连接字符串,以及如何使用web应用程序配置未更改的方式使连接字符串可用。后者实际上是在我之前的多租户文章中解决的在 ASP.NET Core 中执行租户服务我建议使用我此篇文章中提到的BlobStorageTenantProvider

与前一篇文章不同的是,当租户使用不同的数据库时,在这些数据库中不需要租户id。不支持软删除的应用程序可以在使用本文建议的解决方案时使用经典的简单数据上下文。

新的租户类有一个额外的属性- DatabaseConnectionString,如这里所示。

public class Tenant
{
public int Id { get; set; }
public string Name { get; set; }
public string Host { get; set; }
public string DatabaseConnectionString { get; set; }
}

在Azure blob存储中保存的租户配置文件将是这样的。


[
{
"Id": 2,
"Name": "Local host",
"Host": "localhost:30172",
"DatabaseConnectionString": "<connection string 1>"
},
{
"Id": 3,
"Name": "Customer X",
"Host": "localhost:3331",
"DatabaseConnectionString": "<connection string 2>"
},
{
"Id": 4,
"Name": "Customer Y",
"Host": "localhost:33111",
"DatabaseConnectionString": "<connection string 3>"
}
]

返回租户而不是租户ID

由于租户可以定义更多的设置,所以开始处理租户类而不是租户ID。它将改变我的ITenantProvider接口和BlobStorageTenantProvider类。


public class BlobStorageTenantProvider : ITenantProvider
{
private static IList<Tenant> _tenants; private Tenant _tenant; public BlobStorageTenantProvider(IHttpContextAccessor accessor, IConfiguration conf)
{
if(_tenants == null)
{
LoadTenants(conf["StorageConnectionString"], conf["TenantsContainerName"], conf["TenantsBlobName"]);
} var host = accessor.HttpContext.Request.Host.Value;
var tenant = _tenants.FirstOrDefault(t => t.Host.ToLower() == host.ToLower());
if(tenant != null)
{
_tenant = tenant;
}
} private void LoadTenants(string connStr, string containerName, string blobName)
{
var storageAccount = CloudStorageAccount.Parse(connStr);
var blobClient = storageAccount.CreateCloudBlobClient();
var container = blobClient.GetContainerReference(containerName);
var blob = container.GetBlobReference(blobName); blob.FetchAttributesAsync().GetAwaiter().GetResult(); var fileBytes = new byte[blob.Properties.Length]; using (var stream = blob.OpenReadAsync().GetAwaiter().GetResult())
using (var textReader = new StreamReader(stream))
using (var reader = new JsonTextReader(textReader))
{
_tenants = JsonSerializer.Create().Deserialize<List<Tenant>>(reader);
}
} public Tenant GetTenant()
{
return _tenant;
}
}

动态配置数据上下文

我想在这里,多租户应用程序不处理软删除。现在,为了使用正确的连接字符串,必须修改mult-tenant应用程序的默认数据上下文。


public class PlaylistContext : DbContext
{
private readonly Tenant _tenant; public DbSet<Playlist> Playlists { get; set; }
public DbSet<Song> Songs { get; set; } public PlaylistContext(DbContextOptions<PlaylistContext> options,
ITenantProvider tenantProvider)
: base(options)
{
_tenant = tenantProvider.GetTenant();
} protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(_tenant.DatabaseConnectionString); base.OnConfiguring(optionsBuilder);
} protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Playlist>().HasKey(e => e.Id);
modelBuilder.Entity<Song>().HasKey(e => e.Id); base.OnModelCreating(modelBuilder);
}
}

在查看代码时,很容易看出没有多少代码,但它会产生大胆灵活的模型,去支持不同的租户策略。

结束

ASP.NET Core的依赖注入模型和Entity Framework Core的灵活性使得在ASP.NET Core web应用程序中支持更复杂的场景变得非常容易。这篇博文关注的是多租户的一个方面——如何支持每个租户数据存储策略的数据库。如果需要的话,这个模型也可以扩展到更多的设置。

欢迎转载,转载请注明翻译原文出处(本文章),原文出处(原博客地址),然后谢谢观看

如果觉得我的翻译对您有帮助,请点击推荐支持:)

在ASP.NET Core上实施每个租户策略的数据库的更多相关文章

  1. Orchard Core Framework:ASP.NET Core 模块化,多租户框架

    Orchard Core Framework:ASP.NET Core 模块化,多租户框架 上一篇编写Orchard Core一分钟搭建ASP.NET Core CMS ,介绍ASP.NET Core ...

  2. asp.net core上使用Redis探索(2)

    在<<asp.net core上使用Redis探索(1)>>中,我介绍了一个微软官方实现Microsoft.Extensions.Caching.Redis的类库,这次,我们使 ...

  3. asp.net core上使用Redis demo

    整体思路:(1.面向接口编程 2.Redis可视化操作IDE 3.Redis服务) [无私分享:ASP.NET CORE 项目实战(第十一章)]Asp.net Core 缓存 MemoryCache ...

  4. 使用Code First建模自引用关系笔记 asp.net core上使用redis探索(1) asp.net mvc控制器激活全分析 语言入门必学的基础知识你还记得么? 反射

    使用Code First建模自引用关系笔记   原文链接 一.Has方法: A.HasRequired(a => a.B); HasOptional:前者包含后者一个实例或者为null HasR ...

  5. Angular 2的HTML5 pushState在ASP.NET Core上的解决思路

    Angular 2的HTML5 pushState在ASP.NET Core上的解决思路 正如Angular 2在Routing & Navigation中所提及的那样,Angular 2是推 ...

  6. 使用VS Code开发asp.net core (上)

    本文是基于Windows10的. 下载地址: https://code.visualstudio.com/ insider 版下载地址: https://code.visualstudio.com/i ...

  7. ASP.NET Core 上传多文件 超简单教程

    示例源码下载地址 https://qcloud.coding.net/api/project/3915794/files/4463836/download 项目地址 https://dev.tence ...

  8. asp.net core 系列 20 EF基于数据模型创建数据库

    一.概述 本章使用 Entity Framework Core 构建执行基本数据访问的 ASP.NET Core MVC 应用程序.使用迁移(migrations)基于数据模型创建数据库,是一种cod ...

  9. ASP.NET Core 使用 JWT 自定义角色/策略授权需要实现的接口

    目录 ① 存储角色/用户所能访问的 API ② 实现 IAuthorizationRequirement 接口 ③ 实现 TokenValidationParameters ④ 生成 Token ⑤ ...

随机推荐

  1. Codeforces633G(SummerTrainingDay06-I dfs序+线段树+bitset)

    G. Yash And Trees time limit per test:4 seconds memory limit per test:512 megabytes input:standard i ...

  2. js-ES6学习笔记-编程风格(2)

    1.那些需要使用函数表达式的场合,尽量用箭头函数代替.因为这样更简洁,而且绑定了this. 2.所有配置项都应该集中在一个对象,放在最后一个参数,布尔值不可以直接作为参数. 3.不要在函数体内使用ar ...

  3. 百度自动推送js

    <!DOCTYPE html> <!-- saved from url=(0014)about:internet --> <html> <head> & ...

  4. 数据表自增Id获取时IDENTITY的正确使用方式

    在SQLServer中很多表主键会设置为自增列,有的业务需求需要知道新插入的自增Id是多少,一般我们会用SELECT @@IDENTITY来获取,可由于@@IDENTITY是个全局变量作用据较大,所以 ...

  5. Android热修复之 - 阿里开源的热补丁

    1.1 基本介绍 我们先去github上面了解它https://github.com/alibaba/AndFix 这里就有一个概念那就AndFix.apatch补丁用来修复方法,接下来我们看看到底是 ...

  6. 移动端采坑:Position: fixed 在Safari上的Bug

    Position: fixed 在IOS上的显示效果 会出现两种情况: 点击fixed定位的元素会出现fixed定位失效导致的元素贴向底部,即position: absolute,bottom: 0p ...

  7. smarty详细使用教程(韩顺平smarty模板技术笔记)

    MVC是一种开发模式,强调数据的输入.处理.显示是强制分离的 Smarty使用教程1.如何配置我们的smarty解压后把libs文件夹放在网站第一级目录下,然后创建两个文件夹templates 存放模 ...

  8. web调试-禁止/清空chrome页面缓存

    Chrome会对页面缓存,web页面调试的时候,后端修改页面.js之后,刷新页面经常不生效,非常不方便. 有一些小技巧可以解决该问题. 技巧一: 开发者工具-setting/设置,可以关闭缓存. 开发 ...

  9. Python Socket 通信

    参考: http://www.cnblogs.com/alex3714/articles/5830365.html Socket A network socket is an endpoint of ...

  10. mssql 监控随笔

    性能监控列表: •    Memory: Pages/sec   ( 从硬盘上读取或写入硬盘的页数(参考值:00~20) •    Physical Disk: % Disk time 或 Physi ...