美文网首页
Abp框架多租户源码解读及自定义拓展

Abp框架多租户源码解读及自定义拓展

作者: 南城今夏 | 来源:发表于2020-02-07 16:15 被阅读0次

Abp框架多租户源码解读及自定义拓展

1、Abp源码解析

多租户连接字符串处理类(EntityFrameworkCore版本),命名空间为Abp.Zero.EntityFrameworkCore

/// <summary>
/// Implements <see cref="IDbPerTenantConnectionStringResolver"/> to dynamically resolve
/// connection string for a multi tenant application.
/// </summary>
public class DbPerTenantConnectionStringResolver : DefaultConnectionStringResolver, IDbPerTenantConnectionStringResolver

入口方法:

public override string GetNameOrConnectionString(ConnectionStringResolveArgs args)
{
    if (args.MultiTenancySide == MultiTenancySides.Host)
    {
        return GetNameOrConnectionString(new DbPerTenantConnectionStringResolveArgs(null, args));
    }

    return GetNameOrConnectionString(new                                                                     DbPerTenantConnectionStringResolveArgs(GetCurrentTenantId(), args));
}
public class ConnectionStringResolveArgs : Dictionary<string, object>
{
    public MultiTenancySides? MultiTenancySide { get; set; } // 表示当前是租户还是Host

    public ConnectionStringResolveArgs(MultiTenancySides? multiTenancySide = null)
    {
        MultiTenancySide = multiTenancySide;
    }
}

什么时候调用入口方法?初始化DbContext的时候。如iRepository.GetAllList()

这个方法做了什么事情?

public virtual string GetNameOrConnectionString(DbPerTenantConnectionStringResolveArgs args)
{
    if (args.TenantId == null)
    {
        //Host取默认的连接字符串
        return base.GetNameOrConnectionString(args);
    }

    //从缓存中取值
    var tenantCacheItem = _tenantCache.Get(args.TenantId.Value);
    if (tenantCacheItem.ConnectionString.IsNullOrEmpty())
    {
        //租户没配置连接字符串,则返回默认的连接字符串
        return base.GetNameOrConnectionString(args);
    }

    return tenantCacheItem.ConnectionString;
}

看取Host的连接字符串方法:

public virtual string GetNameOrConnectionString(ConnectionStringResolveArgs args)
{
    Check.NotNull(args, nameof(args));

    var defaultConnectionString = _configuration.DefaultNameOrConnectionString;
    if (!string.IsNullOrWhiteSpace(defaultConnectionString))
    {
        return defaultConnectionString;
    }

    if (ConfigurationManager.ConnectionStrings["Default"] != null)
    {
        return "Default";
    }

    if (ConfigurationManager.ConnectionStrings.Count == 1)
    {
        return ConfigurationManager.ConnectionStrings[0].ConnectionString;
    }

    throw new AbpException("Could not find a connection string definition for the application. Set IAbpStartupConfiguration.DefaultNameOrConnectionString or add a 'Default' connection string to application .config file.");
}

问题来了,_tenantCache中哪来的租户配置?看这个Get方法:

public virtual TenantCacheItem Get(int tenantId)
{
    var cacheItem = GetOrNull(tenantId);

    if (cacheItem == null)
    {
        throw new AbpException("There is no tenant with given id: " + tenantId);
    }

    return cacheItem;
}

继续看GetOrNull方法:

public TenantCacheItem GetOrNull(int tenantId)
{
    return _cacheManager
        .GetTenantCache()
        .Get(
            tenantId,
            () =>
            {
                var tenant = GetTenantOrNull(tenantId);
                if (tenant == null)
                {
                    return null;
                }

            return CreateTenantCacheItem(tenant);
            }
        );
}

这个其实就是从缓存中取值,并做了补全功能。继续,看GetTenantOrNull方法:

[UnitOfWork]
protected virtual TTenant GetTenantOrNull(int tenantId)
{
    using (_unitOfWorkManager.Current.SetTenantId(null))
    {
        return _tenantRepository.FirstOrDefault(tenantId);
    }
}

到这里,其实要去租户配置表中查询该租户配置的信息,所以调用了方法_unitOfWorkManager.Current.SetTenantId(null),调用了方法以后,代码执行到_tenantRepository.FirstOrDefault(tenantId)时,会重新调用获取连接字符串的方法,即我们说的入口方法。

最后,拿到Host的数据库连接字符串,_tenantRepository.FirstOrDefault(tenantId)查询当前租户对应的连接字符串。

欢迎大家一起交流学习!

相关文章

  • Abp框架多租户源码解读及自定义拓展

    Abp框架多租户源码解读及自定义拓展 1、Abp源码解析 多租户连接字符串处理类(EntityFrameworkC...

  • ABP 源码解析 二. IOC初始化

    介绍 此系列文章主要是对ABP源码进行解读,初探作者在创造ABP的框架思路,和使用到的设计模式进行。通过解读ABP...

  • ABP 源码解析 七. 日志

    介绍 此系列文章主要是对ABP源码进行解读,初探作者在创造ABP的框架思路,和使用到的设计模式进行。通过解读ABP...

  • ABP 源码解析 八. 设置管理

    介绍 此系列文章主要是对ABP源码进行解读,初探作者在创造ABP的框架思路,和使用到的设计模式进行。通过解读ABP...

  • ABP 源码解析 四. 启动配置

    介绍 此系列文章主要是对ABP源码进行解读,初探作者在创造ABP的框架思路,和使用到的设计模式进行。通过解读ABP...

  • ABP 源码解析 五. Session

    介绍 此系列文章主要是对ABP源码进行解读,初探作者在创造ABP的框架思路,和使用到的设计模式进行。通过解读ABP...

  • ABP 源码解析 一. ABP启动

    介绍 此系列文章主要是对ABP源码进行解读,初探作者在创造ABP的框架思路,和使用到的设计模式进行。通过解读ABP...

  • ABP 源码解析 三. 模块化

    介绍 此系列文章主要是对ABP源码进行解读,初探作者在创造ABP的框架思路,和使用到的设计模式进行。通过解读ABP...

  • ABP 源码解析 六. 缓存

    介绍 此系列文章主要是对ABP源码进行解读,初探作者在创造ABP的框架思路,和使用到的设计模式进行。通过解读ABP...

  • ABP 关闭/打开多租户

    ABP支持多租户,如果使用模板创建ABP项目,缺省支持多租户。如果不希望使用多租户功能,可以修改相关代码,在Web...

网友评论

      本文标题:Abp框架多租户源码解读及自定义拓展

      本文链接:https://www.haomeiwen.com/subject/scamxhtx.html