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