Asp.net core下利用E‎F core实现从数据实现‎多‎租户(2) : 按表分离

来源:m-dot.com   作者:   发表时间:2020-02-16 18:34:12

也提到了这种模式还是相对比较重,所以本文会介绍一种更加普遍使用的办法: 按表分离租户。

在目前的to B的系统中,其实往往会有一个Master数据库,里面使用的是系统中主要的数据,各个租户的数据,往往只是对应的订单、配置、客户信息。

这就造成了,租户的数据不会有很多的种类,他的数据表的数量相对Master来说还是比较少的。

所以在单一租户数据量没有十分庞大的时候,就没有必要对单一租户数据独立到单一数据库。多个租户数据共享使用一个数库是一个折中的选择。

下图就是对应的数据表结构,其中store1和store2使用不同的数据表,但有同一个表名后缀和相同结构。

本文的项目还是沿用上一篇文章的代码,进行加以修改。所以项目中的依赖项还是那些。

但由于代码中有很多命名不好的地方我进行了修改。并且,由于代码结构太简单,对这个示例实现起来不好,进行了少量的结构优化。

1.ModelCacheKeyFactory,这个是EF core提供的对象,主要是要来产生ModelCacheKey

2.ModelCacheKey, 这个跟ModelCacheKeyFactory是一对的,如果需要自定义的话一般要同时实现他们俩

3.ConnectionResolverOption,这个是项目自定义的对象,用于配置。因为我们项目中现在需要同时支持多种租户数据分离的方式

1. 添加ITenantDbContext 接口,它的作用是要来规定StoreDbContext中,必须可以返回TenantInfo。

我们同时也需要修改StoreDbContext去实现ITenantDbContext 接口,并且在构造函数上添加TenantInfo的注入

其中Products已经不是原来简单的一个Property,这里使用DbSet来获取对应的对象,因为表对象还是使用只读Property会好点。

新增一个方法的重写OnModelCreating,这个方法的主要规定EF core 的表实体(本文是Product)怎么跟数据库匹配的,简单来说就是配置。

可以看到表名的规则是TenantInfo.Name "_Products"

2. 创建TenantModelCacheKeyFactory 和TenantModelCacheKey

TenantModelCacheKeyFactory的作用主要是创建TenantModelCacheKey实例。TenantModelCacheKey的作用是作为一个键值,标识dbContext中的OnModelCreating否需要调用。

为什么这样做呢?因为ef core为了优化效率,避免在dbContext每次实例化的时候,都需要重新构建数据实体模型。

在默认情况下,OnModelCreating只会调用一次就会存在缓存。但由于我们创建了TenantModelCacheKey,使得我们有机会判断在什么情况下需要重新调用OnModelCreating

3. 添加ConnectionResolverOption 类和ConnectionResolverType 枚举。

4. 调整MultipleTenancyExtension 的代码结构,并且添加2个扩展函数用于对配置相关的注入。

下面贴出修改过后最主要的3个方法

其中有一个关键的配置, 需要把上文提到的TenantModelCacheKeyFactory 配置到dbOptionBuilder

5. 在TenantSqlConnectionResolver 的GetConnection方法中修改逻辑,让它同时支持按表分离数据和前文的按数据库分离数据

这个类的名字已经改了,前文的命名不合适。 方法中用到的 option 是ConnectionResolverOption 类型,需要加到构造函数。

在本文中,并没有使用Code First配置数据库。所以数据库和数据表需要自行创建。

这样做其实更加贴合项目实际,因为具有这种软件架构的项目,往往需要在新增租户的时候进行自动化处理,普遍做法是准备好一批sql,在新增租户的时候自动在对应的数据库中创建一批表

可能会有人提出疑问,觉得ef core提供的Migration是具有同样的作用的。这个的确是,但是我们这里的表是动态的,ef core生成的Migration plan其实是需要做手动修改的。

Migration 的修改和自定义话是一个大话题,这个需要开另外的文章谈

我们还是跟前文一样,分别使用store1和store2仲添加一些数据。

调动查询所有product接口

store2:

这个示例已经完成了。跟前文一样,是一个实操类型的文章。

下一次我们谈谈怎么根据Schema分离数据。但是Mysql是没有Schema这个概念的,所以我们需要把SqlServer集成进来

但这样把项目的复杂性又提高的。所以这一次必须把代码抽象好了。

编辑:

未经授权许可,不得转载或镜像
© Copyright © 1997-2019 by m-dot.com all rights reserved