/// <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));
        }
Example #3
0
        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 中指定
        }
Example #4
0
 /// <summary>
 /// 使用数据库,如:
 /// <para>var builder = new DbContextOptionsBuilder&lt;TDbContext&gt;(); 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);
        }