/// <summary> /// 获取指定 DbContext 的数据库实例 /// </summary> /// <param name="connectionString">连接字符串,如果为 null,则默认使用 SenparcDatabaseConfigs.ClientConnectionString</param> /// <param name="dbContextOptionsAction">额外配置操作</param> /// <param name="xncfDatabaseData">IXncfDatabase 信息(仅在针对 XNCF 进行数据库迁移时有效)</param> /// <param name="serviceProvider">ServiceProvider</param> /// <returns></returns> public T GetDbContext <T>(string connectionString = null, XncfDatabaseData xncfDatabaseData = null, Action <IRelationalDbContextOptionsBuilderInfrastructure, XncfDatabaseData> dbContextOptionsAction = null, IServiceProvider serviceProvider = null) where T : DbContext { var dbContextType = typeof(T); DbContextOptionsBuilder dbOptionBuilder; var dbOptionBuilderType = dbContextType.GetConstructors().First() .GetParameters().First().ParameterType; if (dbOptionBuilderType.GenericTypeArguments.Length > 0) { //带泛型 //准备创建 DbContextOptionsBuilder 实例,定义类型 dbOptionBuilderType = typeof(DbContextOptionsBuilder <>); //dbOptionBuilderType = typeof(RelationalDbContextOptionsBuilder<,>); //获取泛型对象类型,如:DbContextOptionsBuilder<SenparcEntities> dbOptionBuilderType = dbOptionBuilderType.MakeGenericType(dbContextType); //创建 DbContextOptionsBuilder 实例 dbOptionBuilder = Activator.CreateInstance(dbOptionBuilderType) as DbContextOptionsBuilder; } else { //不带泛型 dbOptionBuilder = new DbContextOptionsBuilder(); } //获取当前数据库配置 var currentDatabasConfiguration = DatabaseConfigurationFactory.Instance.Current; //指定使用当前数据库 currentDatabasConfiguration.UseDatabase( dbOptionBuilder, connectionString ?? SenparcDatabaseConnectionConfigs.ClientConnectionString, xncfDatabaseData, dbContextOptionsAction ); //实例化 DbContext T dbContext; if (serviceProvider == null) { dbContext = Activator.CreateInstance(dbContextType, new object[] { dbOptionBuilder.Options }) as T; } else { dbContext = Activator.CreateInstance(dbContextType, new object[] { dbOptionBuilder.Options, serviceProvider }) as T; } if (dbContext == null) { throw new NcfDatabaseException($"未能创建 {dbContextType.FullName} 的实例", DatabaseConfigurationFactory.Instance.Current.GetType(), null); } return(dbContext); }
public void AddXncfDatabaseModule(IServiceCollection services) { #region 历史解决方案参考信息 /* 参考信息 * 错误信息: * 中文:EnableRetryOnFailure 解决短暂的数据库连接失败 * 英文:Win32Exception: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond * InvalidOperationException: An exception has been raised that is likely due to a transient failure. Consider enabling transient error resiliency by adding 'EnableRetryOnFailure()' to the 'UseSqlServer' call. * 问题解决方案说明:https://www.colabug.com/2329124.html */ /* 参考信息 * 错误信息: * 中文:EnableRetryOnFailure 解决短暂的数据库连接失败 * 英文:Win32Exception: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond * InvalidOperationException: An exception has been raised that is likely due to a transient failure. Consider enabling transient error resiliency by adding 'EnableRetryOnFailure()' to the 'UseSqlServer' call. * 问题解决方案说明:https://www.colabug.com/2329124.html */ #endregion var currentDatabasConfiguration = DatabaseConfigurationFactory.Instance.Current; /* * 非常重要!! * SenparcEntities 工厂配置 */ var xncfDatabaseData = new XncfDatabaseData(this, "Senparc.Service" /*从当前程序集读取*/); Func <IServiceProvider, SenparcEntities> senparcEntitiesImplementationFactory = s => { var multipleDatabasePool = MultipleDatabasePool.Instance; return(multipleDatabasePool.GetDbContext(this.GetType()) as SenparcEntities); }; services.AddScoped <SenparcEntities>(senparcEntitiesImplementationFactory); services.AddScoped <ISenparcEntities>(senparcEntitiesImplementationFactory); services.AddScoped <SenparcEntitiesBase>(senparcEntitiesImplementationFactory); //SystemServiceEntities 工厂配置(实际不会用到) Func <IServiceProvider, SystemServiceEntities> systemServiceEntitiesImplementationFactory = s => { var multipleDatabasePool = MultipleDatabasePool.Instance; return(multipleDatabasePool.GetDbContext(this.GetType()) as SystemServiceEntities); }; services.AddScoped <SystemServiceEntities>(systemServiceEntitiesImplementationFactory); services.AddScoped(typeof(ISqlClientFinanceData), typeof(SqlClientFinanceData)); services.AddScoped(typeof(ISqlBaseFinanceData), typeof(SqlClientFinanceData)); //预加载 EntitySetKey EntitySetKeys.TryLoadSetInfo(typeof(SenparcEntities)); }
public SenparcEntitiesDbContextFactory() : base(Senparc.Core.VersionInfo.VERSION, Path.Combine(AppContext.BaseDirectory, "..\\..\\..\\..\\..\\", "Senparc.Web")) { XncfDatabaseData = new XncfDatabaseData(_systemServiceRegister, null) { AssemblyName = "Senparc.DbMigrations.SQLServer"//强制指定程序集 }; //在 CreateDbContext() 执行之前,指定使用 SQL Server //方法一: //DatabaseConfigurationFactory.Instance.CurrentDatabaseConfiguration = new SQLServerDatabaseConfiguration(); //方法二:在 ServicesAction 中指定 }
/// <summary> /// 使用数据库,如: /// <para>var builder = new DbContextOptionsBuilder<TDbContext>(); builder.UseSqlServer(sqlConnection, DbContextOptionsAction);</para> /// </summary> /// <param name="builder"></param> /// <param name="xncfDatabaseData"></param> /// <param name="connectionString"></param> /// <param name="dbContextOptionsAction">额外需要配置的内容</param> public void UseDatabase(DbContextOptionsBuilder builder, /*IRelationalDbContextOptionsBuilderInfrastructure optionsBuilder,*/ string connectionString, XncfDatabaseData xncfDatabaseData = null, Action <IRelationalDbContextOptionsBuilderInfrastructure, XncfDatabaseData> dbContextOptionsAction = null) { //执行 UseSQLite、UseSQLServer 等操作 SetUseDatabase(builder, connectionString, xncfDatabaseData, b => { //执行基础代码 DbContextOptionsActionBase(b, xncfDatabaseData); //执行扩展代码 DbContextOptionsActionExtension?.Invoke(b, xncfDatabaseData); //执行外部传入的其他方法 dbContextOptionsAction?.Invoke(b, xncfDatabaseData); } ); }
/// <summary> /// 获取指定 xncfDatabaseRegister 关联的当前数据库实例 /// </summary> /// <param name="xncfDatabaseRegisterType">实现了 IXncfDatabase 的具体类型</param> /// <param name="connectionString">连接字符串,如果为 null,则默认使用 SenparcDatabaseConfigs.ClientConnectionString</param> /// <param name="dbContextOptionsAction">额外配置操作</param> /// <param name="xncfDatabaseData">IXncfDatabase 信息(仅在针对 XNCF 进行数据库迁移时有效)</param> /// <param name="serviceProvider">ServiceProvider</param> /// <returns></returns> public DbContext GetXncfDbContext(Type xncfDatabaseRegisterType, string connectionString = null, XncfDatabaseData xncfDatabaseData = null, Action <IRelationalDbContextOptionsBuilderInfrastructure, XncfDatabaseData> dbContextOptionsAction = null, IServiceProvider serviceProvider = null) { if (!typeof(IXncfDatabase).IsAssignableFrom(xncfDatabaseRegisterType)) { throw new NcfDatabaseException($"{nameof(xncfDatabaseRegisterType)} 参数:{xncfDatabaseRegisterType.Name} 必须实现 IXncfDatabase 接口", DatabaseConfigurationFactory.Instance.Current.GetType()); } //获取 DbContext 上下文类型 var dbContextType = GetXncfDbContextType(xncfDatabaseRegisterType); return(this.GetType().GetMethod(nameof(GetDbContext)) .MakeGenericMethod(new Type[] { dbContextType }) .Invoke(this, new object[] { connectionString, xncfDatabaseData, dbContextOptionsAction, serviceProvider }) as DbContext); //return GetDbContext(dbContextType, connectionString, xncfDatabaseData, dbContextOptionsAction, serviceProvider); }