在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 全局查询过滤器

  • 在 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 2.0 web api 基础框架 (1)

  • Asp.Net Core 2.0 多角色权限认证

  • 调试 ASP.NET Core 2.0 源代码

  • Entity Framework Core 2.0 全局查询过滤器

  • 在 ASP.NET Core 中执行租户服务

原文地址: http://www.cnblogs.com/sheng-jie/p/7640163.html 


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/323339.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

nssl1216-码灵鼠【数学】

正题 题目大意 一个序列 a01a_01a0​1 akaiaj(i,j∈[0..k−1])a_ka_ia_j(i,j\in[0..k-1])ak​ai​aj​(i,j∈[0..k−1]) i和j随机选取 求ana_nan​的期望值 解题思路 先打个表不难发现aii1a_ii1ai​i1 之后我们用数学归纳法开始证明 a0011a_0011a0​011 然后用等差序列之和计…

JS中typeof的用法

转载自 JS中typeof的用法 js是一门弱语言&#xff0c;它在声明变量时无需确定变量的类型&#xff0c;js在运行时会自动判断。那么如何判断一个变量的类型呢&#xff0c;js提供了typeof运算符&#xff0c;用来检测一个变量的类型。 1. typeof的语法 typeof是一个运算符&#x…

php动态网站

记得从五六月份就说要建一个可以注册登录的网站了&#xff0c;结果自己两个多月都没能建成&#xff0c;由于学习动态网站实在需要太多知识了&#xff0c;可以说我这几个月的时间都是花在网页上的&#xff0c;从刚开始的htmlcss 到后面的js&#xff0c;js花了太多太多时间&#…

从头编写 asp.net core 2.0 web api 基础框架 (2)

上一篇是: 从头编写 asp.net core 2.0 web api 基础框架 (1) Github源码地址是: https://github.com/solenovex/Building-asp.net-core-2-web-api-starter-template-from-scratch 本文讲的是里面的Step 2. 上一次, 我们使用asp.net core 2.0 建立了一个Empty project, 然后做了…

nssl1217-So many prefix?【KMP】

正题 题目大意 求长度为偶数的前缀在字符串SSS中出现的次数和。 解题思路 我们先不考虑长度为偶数的话&#xff0c;答案很好求。先求出KMP的next数组&#xff0c;然后numinumnexti1num_inum_{next_i}1numi​numnexti​​1。 之后num的和就是答案。 注:num数组表示前i个字符的…

js中toString()和String()区别详解

转载自 js中toString()和String()区别详解 我们知道String()与 .toString()都是可以转换为字符串类型&#xff0c;但是String()与 .toString()的还是有区别的 1、.toString()可以将所有的的数据都转换为字符串&#xff0c;但是要排除null 和 undefined 例如将false转为字符…

java实现上传网络图片到七牛云存储

大家好&#xff0c;我是雄雄。 前言 最近阳了&#xff0c;第二条杠红的发紫&#xff0c;真难受啊&#xff0c;但是吧&#xff0c;博客上有个bug&#xff0c;不解决感觉比阳了还难受。 话还是要从博客的图片显示不出来这里说起&#xff0c;当时做的时候&#xff0c;在发文章这…

【php】php对mysql的连接操作【mysql】

思路&#xff1a; 1、数据库做两个表单&#xff0c;一个是user用来记录用户的信息&#xff0c;方便登录与注册。另一个表单是chat&#xff0c;用来记录聊天内容。 2、用到的技术是ajax&#xff0c;网页及时交互数据&#xff0c;可以做到无刷新聊天。 遍历数据库表单 数据库连…

nssl1218-TRAVEL【SPFA】

正题 题目大意 n个图&#xff0c;有m条双向道路&#xff0c;每条道路有一个l和r。 求一条路径&#xff0c;使得路上最小的r和路上最大的l的差最大。 解题思路 我们考虑枚举l&#xff0c;然后用SPFA计算最大的r。然后这样会超时。 之后我们发现其实答案的l一定是某一条边的l&…

gRPC官方快速上手学习笔记(c#版)

上手前准备工作 支持操作系统&#xff1a;windows、OS X、Linux。实例采用.net、.net core sdk。 The .NET Core SDK command line tools. The .NET framework 4.5 (for OS X and Linux, the open source .NET Framework implementation, “Mono”, at version 4, is suitable…

JS中的加号+运算符详解

转载自 JS中的加号运算符详解 加号运算符 在 JavaScript 中&#xff0c;加法的规则其实很简单&#xff0c;只有两种情况: 把数字和数字相加把字符串和字符串相加 所有其他类型的值都会被自动转换成这两种类型的值。 为了能够弄明白这种隐式转换是如何进行的&#xff0c;我们…

ajax做聊天交互

本想学了几天ajax就可以弄一个类似于qq的网页聊天界面&#xff0c;发现自己想的还是太简单了。 有两个问题无法解决&#xff1a; 1、即使用ajax还是无法保证数据的及时交互&#xff0c;没有办法无时无刻刷新页面。现学的ajax还是依赖于点击事件&#xff0c;才能请求后台数据。 …

ssl提高组周三备考赛【2018.10.24】

前言 快乐题警告&#xff01; 成绩 RankRankRankPersonPersonPersonScoreScoreScoreAAABBBCCC1112017myself2017myself2017myself2102102101001001001001001001010102222017zyc2017zyc2017zyc1581581581001001001818184040403332017xxy2017xxy2017xxy157157157100100100272727…

spring cloud+dotnet core搭建微服务架构:Api网关(三)

前言 国庆假期&#xff0c;一直没有时间更新。 根据群里面的同学的提问&#xff0c;强烈推荐大家先熟悉下spring cloud。文章下面有纯洁大神的spring cloud系列。 上一章最后说了&#xff0c;因为服务是不对外暴露的&#xff0c;所以在外网要访问服务必须通过API网关来完成&…

java实现人脸识别源码【含测试效果图】——前期准备工作及访问提示

注意&#xff1a; 看完之后如有不懂&#xff0c;请看&#xff1a;关于人脸和指纹识别共同交流方案&#xff0c;也可以关注微信公众号&#xff1a;雄雄的小课堂&#xff0c;回复&#xff1a;人脸识别群获取群号&#xff0c;群内有直接可以运行的源码可供下载&#xff0c;人脸识…

JS原型链与instanceof底层原理

转载自 JS原型链与instanceof底层原理 一、问题&#xff1a; instanceof 可以判断一个引用是否属于某构造函数&#xff1b; 另外&#xff0c;还可以在继承关系中用来判断一个实例是否属于它的父类型。 老师说&#xff1a;instanceof的判断逻辑是&#xff1a; 从当前引用的…

P2522-[HAOI2011]Problem b【莫比乌斯反演】

正题 题目大意 求∑iab∑jcd(gcd(i,j)k)\sum_{ia}^b\sum_{jc}^d(gcd(i,j)k)ia∑b​jc∑d​(gcd(i,j)k) 解题思路 定义 f(i)∑i1n∑j1m(gcd(i,j)i)f(i)\sum_{i1}^n\sum_{j1}^m(gcd(i,j)i)f(i)i1∑n​j1∑m​(gcd(i,j)i) 然后计算f利用容斥计算答案 之后我们考虑如何计算 F(i)…

正则之注册登录

不久前写了个登录注册的网站&#xff0c;因为未对其做出限制&#xff0c;所以&#xff0c;随便你输入什么都可以注册成功&#xff0c;遂想怎么通过js规定注册的账号 我的要求是&#xff1a; 一&#xff1a;输入框不能为空&#xff0c;不能太长也不能太短 二&#xff1a; 1、注…

猿创征文|从酒店前台收银到软件研发教学主管到技术经理之路~

大家好&#xff0c;我是雄雄。 内容先知&#x1f449;前言☝酒店收银&#x1f928;项目组长&#x1f91c;OA管理系统&#x1f91c;酒店管理系统&#x1f468;‍&#x1f3eb;软件研发讲师&#x1f4cc;学术主管&#x1f468;‍&#x1f4bb;技术经理&#x1f449;项目情况&…

微服务~分布式事务里的最终一致性

本地事务ACID大家应该都知道了&#xff0c;统一提交&#xff0c;失败回滚&#xff0c;严格保证了同一事务内数据的一致性&#xff01;而分布式事务不能实现这种ACID&#xff0c;它只能实现CAP原则里的某两个&#xff0c;CAP也是分布式事务的一个广泛被应用的原型&#xff0c;CA…