设为首页 加入收藏

TOP

EF Core 实现读写分离的最佳方案(二)
2019-10-09 19:59:10 】 浏览:162
Tags:Core 实现 读写 分离 最佳 方案
rovider)); _serviceProvider = serviceProvider; _dbContext = context; _repositoryFactory = serviceProvider.GetRequiredService<IRepositoryFactory>(); } public DbContext DbContext { get => _dbContext; } public IReadOnlyRepository<TEntity, TKey> GetReadOnlyRepository<TEntity, TKey>() where TEntity : class, IEntity<TKey> where TKey : IEquatable<TKey> { return _repositoryFactory.GetReadOnlyRepository<TEntity, TKey>(this); } public IRepository<TEntity, TKey> GetRepository<TEntity, TKey>() where TEntity : class, IEntity<TKey> where TKey : IEquatable<TKey> { return _repositoryFactory.GetRepository<TEntity, TKey>(this); } public void Dispose() { if (_disposed) { return; } _dbContext?.Dispose(); _disposed = true; } // 其他略 }
    /// <summary>
    /// 数据库提供者接口
    /// </summary>
    public interface IDbProvider : IDisposable
    {
        /// <summary>
        /// 根据上下文类型及数据库名称获取UnitOfWork对象, dbName为null时默认为第一个数据库名称
        /// </summary>
        IUnitOfWork GetUnitOfWork(Type dbContextType, string dbName = null);
    }

IDbProvider 接口, 根据上下文类型和配置文件中的数据库连接字符串名称创建IUnitOfWork, 在DI中的生命周期是Scoped,在销毁的同时会销毁数据库上下文对象, 下面是它的实现, 为了提高性能使用了Expression来代替反射.

public class DbProvider : IDbProvider
    {
        private readonly IServiceProvider _serviceProvider;
        private readonly ConcurrentDictionary<string, IUnitOfWork> _works = new ConcurrentDictionary<string, IUnitOfWork>();
        private static ConcurrentDictionary<Type, Func<IServiceProvider, DbContextOptions, DbContext>> _expressionFactoryDict =
            new ConcurrentDictionary<Type, Func<IServiceProvider, DbContextOptions, DbContext>>();

        public DbProvider(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }

        public IUnitOfWork GetUnitOfWork(Type dbContextType, string dbName = null)
        {
            var key = string.Format("{0}${1}$", dbName, dbContextType.FullName);
            IUnitOfWork unitOfWork;
            if (_works.TryGetValue(key, out unitOfWork))
            {
                return unitOfWork;
            }
            else
            {
                DbContext dbContext;
                var dbConnectionOptionsMap = _serviceProvider.GetRequiredService<IOptions<FxOptions>>().Value.DbConnections;
                if (dbConnectionOptionsMap == null || dbConnectionOptionsMap.Count <= 0)
                {
                    throw new Exception("无法获取数据库配置");
                }

                DbConnectionOptions dbConnectionOptions = dbName == null ? dbConnectionOptionsMap.First().Value : dbConnectionOptionsMap[dbName];

                var builderOptions = _serviceProvider.GetServices<DbContextOptionsBuilderOptions>()
                     ?.Where(d => (d.DbName == null || d.DbName == dbName) && (d.DbContextType == null || d.DbContextType == dbContextType))
                     ?.OrderByDescending(d => d.DbName)
                     ?.OrderByDescending(d => d.DbContextType);
                if (builderOptions == null || !builderOptions.Any())
                {
                    throw new Exception("无法获取匹配的DbContextOptionsBuilder");
                }

                var dbUser = _serviceProvider.GetServices<IDbContextOptionsBuilderUser>()?.FirstOrDefault(u => u.Type == dbConnectionOptions.DatabaseType);
                if (dbUser == null)
                {
                    throw new Exception($"无法解析类型为“{dbConnectionOptions.DatabaseType}”的 {typeof(IDbContextOptionsBuilderUser).FullName} 实例");
                }
                
                var dbContextOptions = dbUser.Use(builderOptions.First().Buil
首页 上一页 1 2 3 4 5 下一页 尾页 2/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇矩阵连乘求解优化 下一篇在 ASP.NET Core 项目中使用 Auto..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目