在ASP.NET Core上实施每个租户策略的数据库
在ASP.NET Core上实施每个租户策略的数据库
不定时更新翻译系列,此系列更新毫无时间规律,文笔菜翻译菜求各位看官老爷们轻喷,如觉得我翻译有问题请挪步原博客地址
本博文翻译自:
http://gunnarpeipman.com/2017/08/database-per-tenant/
让我们继续使用ASP.NET Core web应用程序中的多租户,并关注每个租户都有自己的数据库的解决方案。它不仅仅是关于数据库的——可以有更多的服务,每个租户都有自己的实例。它使这里提供的解决方案可以轻松地扩展到除SQL Server或其他任何关系数据库之外的其他服务。
以往的工作
在讨论解决方案之前,我建议先浏览一下我以前的文章,内容包括ASP.NET Core web应用程序中的多租户的一些方面:
- [Entity Framework Core 2.0 全局查询过滤器](http://www.cnblogs.com/chen-jie/p/ef-core-global-query-filters.html"Global query filters in Entity Framework Core 2.0")
- 在 ASP.NET Core 中执行租户服务
注意! 本文中的代码建立在上述文章的代码之上。
将数据库连接字符串移动到租户配置
这里的问题是如何动态决定使用哪个连接字符串,以及如何使用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上实施每个租户策略的数据库的更多相关文章
- Orchard Core Framework:ASP.NET Core 模块化,多租户框架
Orchard Core Framework:ASP.NET Core 模块化,多租户框架 上一篇编写Orchard Core一分钟搭建ASP.NET Core CMS ,介绍ASP.NET Core ...
- asp.net core上使用Redis探索(2)
在<<asp.net core上使用Redis探索(1)>>中,我介绍了一个微软官方实现Microsoft.Extensions.Caching.Redis的类库,这次,我们使 ...
- asp.net core上使用Redis demo
整体思路:(1.面向接口编程 2.Redis可视化操作IDE 3.Redis服务) [无私分享:ASP.NET CORE 项目实战(第十一章)]Asp.net Core 缓存 MemoryCache ...
- 使用Code First建模自引用关系笔记 asp.net core上使用redis探索(1) asp.net mvc控制器激活全分析 语言入门必学的基础知识你还记得么? 反射
使用Code First建模自引用关系笔记 原文链接 一.Has方法: A.HasRequired(a => a.B); HasOptional:前者包含后者一个实例或者为null HasR ...
- Angular 2的HTML5 pushState在ASP.NET Core上的解决思路
Angular 2的HTML5 pushState在ASP.NET Core上的解决思路 正如Angular 2在Routing & Navigation中所提及的那样,Angular 2是推 ...
- 使用VS Code开发asp.net core (上)
本文是基于Windows10的. 下载地址: https://code.visualstudio.com/ insider 版下载地址: https://code.visualstudio.com/i ...
- ASP.NET Core 上传多文件 超简单教程
示例源码下载地址 https://qcloud.coding.net/api/project/3915794/files/4463836/download 项目地址 https://dev.tence ...
- asp.net core 系列 20 EF基于数据模型创建数据库
一.概述 本章使用 Entity Framework Core 构建执行基本数据访问的 ASP.NET Core MVC 应用程序.使用迁移(migrations)基于数据模型创建数据库,是一种cod ...
- ASP.NET Core 使用 JWT 自定义角色/策略授权需要实现的接口
目录 ① 存储角色/用户所能访问的 API ② 实现 IAuthorizationRequirement 接口 ③ 实现 TokenValidationParameters ④ 生成 Token ⑤ ...
随机推荐
- DVWA的安装
DVWA(Dam Vulnerable Web Application)是基于PHP+Mysql的一套用于常规Web漏洞教学和检测Web脆弱性测试程序,包含了SQL注入,Xss,盲注等常用的一些安全漏 ...
- 排序算法(7)--exchang Sorting--交换排序[2]--Quick Sort--快速排序
1.基本思想 从待排序列中选取一元素作为轴值(也叫主元). 将序列中的剩余元素以该轴值为基准,分为左右两部分.左部分元素不大于轴值,右部分元素不小于轴值.轴值最终位于两部分的分割处. 对左右两部分重复 ...
- BZOJ5323:[JXOI2018]游戏
传送门 不难发现,所有不能被其他数筛掉的数是一定要选的,只有选了这些数字才能结束 假设有 \(m\) 个,枚举结束时间 \(x\),答案就是 \(\sum \binom{x-1}{m-1}m!(n-m ...
- JSP内置对象——response对象
看一个实例: 运行结果: 出现了一个很奇怪的现象,这个outer对象输出的字符串,跑到顶部去了.这个呢也就说明了response对象获得的writer对象的输出总是前于我们的内置对象.(respons ...
- ngnix https
server { listen 80;#端口号 server_name www.xxxx.net;#本机 charset ...
- Mongodb集群与分片 2
前面我们介绍了简单的集群配置实例.在简单实例中,虽然MongoDB auto-Sharding解决了海量存储问题,和动态扩容问题,但是离我们在真实环境下面所需要的高可靠性和高可用性还有一定的距离. 下 ...
- cent7安装ffmpeg
FFmpeg是一个领先的多媒体框架工具集,几乎能够对任何格式的音视频文件进行解码,编码,转码,复用,解复用,流式传输,过滤和播放. 不管这些音视频文件所采用的格式是由某些标准委员会,社区还是公司设计的 ...
- Python中可视化图表处理echarts库的安装
系统环境:Windows 7 企业版 进入cmd 输入:python –m pip install pyecharts
- 浅析C#中的Attribute
原文地址:http://www.cnblogs.com/hyddd/archive/2009/07/20/1526777.html 一.什么是Attribute 先看下面的三段代码: 1.自定义Att ...
- orcl创建表及管理表
常用的字段数据类型: .字符串(varchar2(n)) n表示保存最大长度,基本200作用..整数(number(n)) n位的整数,也可用int代替.小数(number(n,m)) m为小数位,n ...