在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. python去掉字符串中空格的方法

    1.strip():把头和尾的空格去掉 2.lstrip():把左边的空格去掉 3.rstrip():把右边的空格去掉 4.replace('c1','c2'):把字符串里的c1替换成c2.故可以用r ...

  2. python-工厂方法模式

    源码地址:https://github.com/weilanhanf/PythonDesignPatterns 简单工厂模式的不足: 在简单工厂模式中,只提供了一个工厂类,该工厂类处于对产品类进行实例 ...

  3. Mysql数据库 的库表简易操作

    一. 库的操作 1.创建数据库 创建数据库: create database 库名 charset utf8;   charset uft8  可选项 1.2 数据库命名规范: 可以由字母.数字.下划 ...

  4. [基础架构]PeopleSoft Tuxedo 重要文件说明

    我们都知道PeopleSoft是由几个不同的服务组成的,他们在PeopleSoft体系结构中扮演着自己的角色.这些服务具有不同的文件结构并包含重要的可执行文件和配置文件. 以下是Peoplesoft体 ...

  5. Visual Studio编译C工程出现的错误

    错误1. エラー 1 error LNK1561: エントリー ポイントを定義しなければなりません. 解决办法:将工程的类型改为dll动态库,设置方式如下: 右键工程,选择[プロパティ].在弹出的面板 ...

  6. 实现网络数据提取你需要哪些java知识

    本篇对一些常用的java知识做一个整合,三大特性.IO操作.线程处理.类集处理,目的在于能用这些只是实现一个网页爬虫的功能. Ⅰ 首先对于一个java开发的项目有一个整体性的了解认知,项目开发流程: ...

  7. 网站与phpwind用户同步的方法

    搭建了一个个人网站,希望使用phpwind来完成论坛功能.但很快就发现存在用户同步的问题,我的网站已经有了用户管理功能, phpwind论坛也有.因此用户同步注册,登陆和注销是必须要实现的. 网上说可 ...

  8. 【转】设置Qt应用程序图标及应用程序名

    一直以来很纠结给qt应用程序添加图标问题,在网上收过一次,但是感觉不够完整,现将自己的实现过程记录下,以便以后查看: 通过网上的例子知道qt助手中有相关说明: Setting the Applicat ...

  9. 目标管理之SMART原则

    SMART原则经常用于KPI制定,也可以用于个人目标管理. SMART原则: S(Specific):目标必须是具体的,需要对标特定的工作目标,不能笼统: M(Measurable):目标必须是可衡量 ...

  10. SerialPort类的用法与示例

    转:https://www.cnblogs.com/hwBeta/p/6926363.html Microsoft .Net框架SerialPort类的用法与示例 从Microsoft .Net 2. ...