博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
EF Ccore 主从配置 最简化
阅读量:5172 次
发布时间:2019-06-13

本文共 5452 字,大约阅读时间需要 18 分钟。

业务需要 配置一主多从数据库 读写分离  orm用的ef core , 把思路和代码写下

1. 配置2个数据库上下文 ETMasterContext  ETSlaveContext(把增删改功能禁用掉)

public class ETMasterContext : DbContext

     {
         public ETMasterContext(DbContextOptions<ETMasterContext> options)
             : base(options)
         {

        }

         public DbSet<User> Users { get; set; }

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

            modelBuilder.ApplyConfiguration(new UserConfiguration());

         }
     }

public class ETSlaveContext : DbContext

     {
         public ETSlaveContext(DbContextOptions<ETSlaveContext> options)
             : base(options)
         {

        }

        public DbSet<User> Users { get; set; }

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

            modelBuilder.ApplyConfiguration(new UserConfiguration());

         }
         public override int SaveChanges()
         {
             throw new InvalidOperationException("只读数据库,不允许写入");
         }
         public override int SaveChanges(bool acceptAllChangesOnSuccess)
         {
             throw new InvalidOperationException("只读数据库,不允许写入");
         }
         public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default)
         {
             throw new InvalidOperationException("只读数据库,不允许写入");
         }
         public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
         {
             throw new InvalidOperationException("只读数据库,不允许写入");
         }

    }

2. 定义2个Repository  EfRepository(主)    EfReadOnlyRepository(只读)

public class EfRepository<T> : IRepository<T> where T : EntityBase

     {
         protected readonly ETMasterContext Context;

        public EfRepository(ETMasterContext context)

         {
             Context = context;
             //Context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
         }

        public IQueryable<T> Table => Context.Set<T>().AsQueryable();

        public IQueryable<T> TableNoTracking => Context.Set<T>().AsNoTracking();

        public int Delete(T entity)

         {
             try
             {
                 Context.Set<T>().Remove(entity);
                 return 1;
             }
             catch (Exception)
             {

                return 0;

             }
         }

        public int DeleteWhere(Expression<Func<T, bool>> criteria)

         {
             try
             {
                 IQueryable<T> entities = Context.Set<T>().Where(criteria);
                 foreach (var entity in entities)
                 {
                     Context.Entry(entity).State = EntityState.Deleted;
                 }
                 return 1;
             }
             catch (Exception)
             {
                 return 0;
             }

        }

        public T GetById(object id)

         {
             return Context.Set<T>().Find(id);
         }

        public int Insert(T entity)

         {
             try
             {
                 Context.Set<T>().Add(entity);
                 return 1;
             }
             catch (Exception ex)
             {
                 return 0;
             }

        }

        public int InsertMany(IEnumerable<T> list)

         {
             try
             {
                 Context.Set<T>().AddRange(list);
                 return 1;
             }
             catch (Exception ex)
             {
                 return 0;
             }
         }

        public int Update(T entity)

         {
             try
             {
                 Context.Entry(entity).State = EntityState.Modified;
                 return 1;
             }
             catch (Exception)
             {
                 return 0;
             }
         }
     }

public class EfReadOnlyRepository<T> : IReadOnlyRepository<T> where T : EntityBase

     {
         protected readonly ETSlaveContext Context;

        public EfReadOnlyRepository(ETSlaveContext context)

         {
             Context = context;
             //Context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
         }

        public IQueryable<T> Table => Context.Set<T>().AsQueryable();

        public IQueryable<T> TableNoTracking => Context.Set<T>().AsNoTracking();

        public T GetById(object id)

         {
             return Context.Set<T>().Find(id);
         }
     }

3. 用到的接口补上

public interface IReadOnlyRepository<T> where T : EntityBase

{
     IQueryable<T> Table { get; }

    IQueryable<T> TableNoTracking { get; }

     T GetById(object id);
}

public interface IRepository<T> : IReadOnlyRepository<T> where T : EntityBase

{
     int Insert(T entity);
     int InsertMany(IEnumerable<T> list);
     int Update(T entity);
     int Delete(T entity);
     int DeleteWhere(Expression<Func<T, bool>> criteria);
}

4. Startup  ConfigureServices 中配置上下文

services.AddDbContext<ETMasterContext>(options =>

     options.UseMySql(GetConnectionStringByRandom("MySql_Master")));
services.AddDbContext<ETSlaveContext>(options =>
     options.UseMySql(GetConnectionStringByRandom("MySql_Slave")));

private string GetConnectionStringByRandom(string connectionString)

{
     var connstr = Configuration.GetConnectionString(connectionString);
     if (string.IsNullOrEmpty(connstr))
     {
         throw new Exception("数据库配置有误");
     }

    var conList = connstr.Trim('|').Split('|');

     var rand = new Random().Next(0, conList.Length);
     return conList[rand];
}

5. appsetting.json 配置多个连接字符串  | 分隔

"connectionStrings": {

   "MySql_Master": "server=192.168.87.169;database=poker_games;uid=root;pwd=1$=6yuan;SslMode=None;",
   "MySql_Slave": "server=192.168.87.169;database=poker_games;uid=root;pwd=1$=6yuan;SslMode=None;|server=192.168.87.169;database=poker_games;uid=root;pwd=1$=6yuan;SslMode=None;"
}

6. 实际应用

public class ReportService : IReportService

     {
         private readonly IHttpContextAccessor _httpContextAccessor;
         private readonly IDistributedCache _distributedCache;
         private readonly IUnitOfWork _unitOfWork;
         private readonly IMapper _mapper;
         private readonly IReadOnlyRepository<Bet> _betRepository;

        public ReportService(

             IHttpContextAccessor httpContextAccessor,
             IDistributedCache distributedCache,
             IUnitOfWork unitOfWork,
             IMapper mapper,
             IReadOnlyRepository<Bet> betRepository
             )
         {
             _httpContextAccessor = httpContextAccessor;
             _distributedCache = distributedCache;
             _unitOfWork = unitOfWork;
             _mapper = mapper;
             _betRepository = betRepository;
         }

}

public ReturnValue GetAgentBetReportByRound(AgentBetReportByRoundCriteriaModel reportModel)

         {
            

            var betList = _betRepository.TableNoTracking.Where(p => p.pay_out_date >= beginTime && p.pay_out_date < endTime);

            
             return new ReturnValue(betList );

        }

7. 大概解释下

如图 DBContext的生命周期默认是Scoped,即整个reqeust请求的生命周期以内共用了一个Context

利用这个生命周期 在每次请求时 通过配置文件获取不同的上下文实例 即实现了 多主多从 读写分离功能

转载于:https://www.cnblogs.com/xtxtx/p/10795236.html

你可能感兴趣的文章
django orm 数据查询详解
查看>>
JarvisOJ Basic 熟悉的声音
查看>>
C# list导出Excel(二)
查看>>
CAS 单点登录模块学习
查看>>
Android应用开发-网络编程①
查看>>
input中的name,value以及label中的for
查看>>
静态库制作-混编(工程是oc为基础)
查看>>
jQuery 显示加载更多
查看>>
Confluence 6 系统运行信息中的 JVM 内存使用情况
查看>>
Confluence 6 升级以后
查看>>
用JS实现版面拖拽效果
查看>>
二丶CSS
查看>>
《avascript 高级程序设计(第三版)》 ---第二章 在HTML中使用Javascript
查看>>
JS一些概念知识及参考链接
查看>>
TCP/IP协议原理与应用笔记24:网际协议(IP)之 IP协议的简介
查看>>
SAP HANA开发中常见问题- 基于SAP HANA平台的多团队产品研发
查看>>
游戏中的心理学(一):认知失调有前提条件
查看>>
WHAT I READ FOR DEEP-LEARNING
查看>>
【Ruby】Ruby在Windows上的安装
查看>>
Objective C 总结(十一):KVC
查看>>