<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Ef Core花里胡哨系列(10) 動態起來的 DbContext

      Ef Core花里胡哨系列(10) 動態起來的 DbContext

      我們知道,DbContext有兩種托管方式,一種是AddDbContextAddDbContextFactory,但是呢他們各有優劣,例如工廠模式下性能更好呀等等。那么,我們能否自己托管DbContext呢?

      Github Demo:動態起來的 DbContext

      場景:
      結合我們之前的文章 [Ef Core花里胡哨系列(5) 動態修改追蹤的實體、動態查詢] 假設一個應用內有很多的子應用,且都需要更新追蹤的動態實體,那么很多表在重置OnModelCreating的時候將會非常的慢。主要體現在modelBuilder.Model.AddEntityType(type),每個實體都需要花費一小段時間,幾百個實體就會按分鐘計算了,而且還會數據庫操作產生一定的影響。

      我們先實現一個基礎的DbContext用來添加一些通用的實體以及處理動態實體的邏輯,每次需要重置DbContext的時候,都會獲取最新的動態實體進行更新:

      public class DbContextBase : DbContext
      {
          public DbSet<User> Users { get; set; } = null!;
          public DbSet<Department> Departments { get; set; } = null!;
      
          protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
          {
              optionsBuilder.UseSqlite("Data Source=sample.db");
              optionsBuilder.ReplaceService<IModelCacheKeyFactory, MyModelCacheFactory>();
      
              base.OnConfiguring(optionsBuilder);
          }
      
          protected override void OnModelCreating(ModelBuilder modelBuilder)
          {
              var name = GetType().Name.Split("_");
              if (name.Length > 1)
              {
                  foreach (var item in FormTypeBuilder.GetAppTypes(name[0]).Where(item => modelBuilder.Model.FindEntityType(item.Value) is null))
                  {
                      modelBuilder.Model.AddEntityType(item.Value);
                  }
              }
      
              base.OnModelCreating(modelBuilder);
          }
      }
      

      然后實現一個動態DbContext的生成器,用于針對不同的AppId生成不同的DbContext

      public class DbContextGenerator
      {
          private readonly ConcurrentDictionary<string, Type> _contextTypes = new()
          {
          };
      
          public Type GetOrCreate(string appId)
          {
              if (!_contextTypes.TryGetValue(appId, out var value))
              {
                  value = GeneratorDbContext(appId);
                  _contextTypes.TryAdd(appId, value);
              }
      
              return value;
          }
      
          public Type GeneratorDbContext(string appId)
          {
              var assemblyName = new AssemblyName("__RuntimeDynamicDbContexts");
              var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
              var moduleBuilder = assemblyBuilder.DefineDynamicModule("__RuntimeDynamicModule");
              var typeBuilder = moduleBuilder.DefineType($"{appId.ToLower()}_DbContext", TypeAttributes.Public | TypeAttributes.Class, typeof(DbContextBase));
              var constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[] { });
              var ilGenerator = constructorBuilder.GetILGenerator();
              ilGenerator.Emit(OpCodes.Ldarg_0);
              ilGenerator.Emit(OpCodes.Call, typeof(DbContextBase).GetConstructor(Type.EmptyTypes));
              ilGenerator.Emit(OpCodes.Ret);
              typeBuilder.CreateType();
              var dbContextType = assemblyBuilder.GetType($"{appId.ToLower()}_DbContext");
              return dbContextType;
          }
      }
      

      然后我們需要實現一個DbContext的容器用于管理我們生成的DbContext,以及負責初始化:

      public class DbContextContainer : IDisposable
      {
          private readonly DbContextGenerator _generator;
          private readonly Dictionary<string, DbContext> _contexts = new();
      
          public DbContextContainer(DbContextGenerator generator)
          {
              _generator = generator;
          }
      
          public DbContext Get(string appId)
          {
              if (!_contexts.TryGetValue(appId, out var context))
              {
                  context = (DbContext)Activator.CreateInstance(_generator.GetOrCreate(appId))!;
                  _contexts[appId] = context;
              }
      
              return context;
          }
      
          public void Dispose()
          {
              _contexts.Clear();
          }
      }
      

      DbContextContainer的生命周期即DbContext的生命周期,因為DbContext的緩存是共享的,所以我們也不用擔心一些性能問題。

      使用時也非常簡單,我們只需要在DbContextContainer取出我們對應AppIdDbContext進行操作就可以了:

      public class DynamicController : ApiControllerBase
      {
          private readonly DbContextContainer _container;
      
          public DynamicController(DbContextContainer container)
          {
              _container = container;
          }
      
          [HttpGet]
          public async Task<IActionResult> GetCompanies()
          {
              var res = await _container.Get("test1").DynamicSet(typeof(Company)).ToDynamicListAsync();
      
              return Ok(res);
          }
      
          [HttpGet]
          public async Task<IActionResult> AddCompany()
          {
              var db = _container.Get("test1");
              FormTypeBuilder.AddDynamicEntity("test1", "Companies", typeof(Company));
              db.UpdateVersion();
      
              return Ok();
          }
      }
      
      posted @ 2024-01-04 11:43  胖紙不爭  閱讀(1139)  評論(9)    收藏  舉報
      主站蜘蛛池模板: 另类 专区 欧美 制服丝袜| 国产好大好硬好爽免费不卡| 国产自产对白一区| 精品国产午夜福利在线观看| 一区二区三区四区高清自拍| 国模粉嫩小泬视频在线观看| 日本欧美大码a在线观看| 欧美影院成年免费版| 国产精品午夜福利小视频| 丁香色婷婷国产精品视频| 熟女精品色一区二区三区| 石河子市| 免费无码黄十八禁网站| 国产精品小仙女自拍视频| 日本久久精品一区二区三区| 热久在线免费观看视频| 久久中文字幕一区二区| 日韩熟女熟妇久久精品综合| 亚洲人成小说网站色在线| 樱桃视频影院在线播放| 国产成人精品无人区一区| 性色在线视频精品| 国产网友愉拍精品视频手机| 精品免费看国产一区二区| 国产日韩av二区三区| 欧美日韩亚洲国产| 麻豆国产高清精品国在线| 蜜桃久久精品成人无码av| 精品一区二区中文字幕| 午夜综合网| 天天夜碰日日摸日日澡性色av| 欧美videosdesexo吹潮| 老熟妇欲乱一区二区三区| 乌克兰美女浓毛bbw| 中文字幕一区二区人妻| 国产精品无码不卡在线播放| 国产精品久久久久鬼色| 欧美视频二区欧美影视| 色五开心五月五月深深爱| 国产精品亚洲二区在线看| 丁香五月亚洲综合在线国内自拍|