ABP vNext 實現租戶Id自動賦值插入

背景

在使用ABP vNext過程中,因爲我們的用戶體系龐大,所以一直與其他業務同時開發,在開發其他業務模塊時,我們一直存在着誤區:認爲ABP vNext 自動處理了數據新增時的租戶Id(TenantId)的自動賦值插入。直到我們開始接入用戶權限模塊後,發現並不如此。

思路

爲了實現字段的自動賦值,且無感知的,我們的思路是做類似攔截器,在上層應用新增數據相關代碼流程進入DbContext的時候,在DbContext中進行處理。

其他

問題

爲了實現上層業務開發人員的【無感知】,哪怕在代碼編寫過程中,我們也不希望開發人員有所明顯感知自己在使用經過處理的DbContext,於是想到了與Volo.Abp.EntityFrameworkCore.AbpDbContext使用同一個名字AbpDbContext。

解決方案

我們首先知道,在C#中,如果有兩個命名空間下,具有同名類,那麼兩個類的優先級爲何。

假設,我們寫的類:TripleH.AbpDbContext。我們在使用這個類的地方的命名空間爲:TripleH.*.AClass。

那麼在AClass中使用AbpDbContext時,我們就算引用了Volo.Abp.EntityFrameworkCore命名空間,編譯時也會使用TripleH.AbpDbContext。

這是因爲,C#在此處的優先級決定的,它優先找Triple.*命名空間下的AbpDbContext這個類,如果沒有,就會逐級往上,找Triple命名空間下的AbpDbContext,如果找到了,就會直接使用它,使用時連命名空間都不需要手動引用。當然,如果沒找過,纔會去其他命名空間如Volo.Abp.EntityFrameworkCore中尋找。

實現

namespace TripleH
{
    public abstract class AbpDbContext<TDbContext> : Volo.Abp.EntityFrameworkCore.AbpDbContext<TDbContext>
        where TDbContext : AbpDbContext<TDbContext>
    {
        public AbpDbContext(DbContextOptions<TDbContext> options)
            : base(options)
        {

        }

        protected override void ApplyAbpConceptsForAddedEntity(EntityEntry entry, EntityChangeReport changeReport)
        {
            SetTenantIdIfNull(entry);
            base.ApplyAbpConceptsForAddedEntity(entry, changeReport);
        }

        protected virtual void SetTenantIdIfNull(EntityEntry entry)
        {
            if (entry.Entity is IMultiTenant entityWithTenantId
                && entityWithTenantId.TenantId == null
                && IsMultiTenantFilterEnabled)
            {
                ObjectHelper.TrySetProperty(entityWithTenantId, e => e.TenantId, () => CurrentTenant.Id);
            }
        }
    }
}

使用

//無需額外引用TripleH命名空間,做到真正的無感知,當然鼠標放到AbpDbContext上,VS 會告訴你是哪個命名空間
namespace TripleH.Test.EntityFrameworkCore
{
    //此處繼承的AbpDbContext,便是來自TripleH命名空間下,而非Abp
    [ConnectionStringName(BasicDbProperties.ConnectionStringName)]
    public class BasicDbContext : AbpDbContext<BasicDbContext>, IBasicDbContext
    {
        public BasicDbContext(DbContextOptions<BasicDbContext> options)
            : base(options)
        {

        }

        protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);

            builder.ConfigureBasic();
        }
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章