public ClientRepositoryBase(ISqlBaseFinanceData db) { //System.Web.HttpContext.Current.Response.Write("-"+this.GetType().Name + "<br />"); var keys = EntitySetKeys.GetEntitySetKeys(base.BaseDB.BaseDataContext.GetType()); _entitySetName = keys[typeof(T)]; }
/// <summary> /// 添加模块 /// </summary> /// <param name="services"></param> /// <returns></returns> public virtual IServiceCollection AddXscfModule(IServiceCollection services, IConfiguration configuration) { if (this is IXscfDatabase databaseRegister) { //定义 XscfSenparcEntities 实例生成 Func <IServiceProvider, object> implementationFactory = s => { //准备创建 DbContextOptionsBuilder 实例,定义类型 var dbOptionBuilderType = typeof(DbContextOptionsBuilder <>); //获取泛型对象类型,如:DbContextOptionsBuilder<SenparcEntity> dbOptionBuilderType = dbOptionBuilderType.MakeGenericType(databaseRegister.XscfDatabaseDbContextType); //创建 DbContextOptionsBuilder 实例 DbContextOptionsBuilder dbOptionBuilder = Activator.CreateInstance(dbOptionBuilderType) as DbContextOptionsBuilder; //继续定义配置 dbOptionBuilder = SqlServerDbContextOptionsExtensions.UseSqlServer(dbOptionBuilder, Scf.Core.Config.SenparcDatabaseConfigs.ClientConnectionString, b => databaseRegister.DbContextOptionsAction(b, null)); //创建 SenparcEntities 实例 var xscfSenparcEntities = Activator.CreateInstance(databaseRegister.XscfDatabaseDbContextType, new object[] { dbOptionBuilder.Options }); return(xscfSenparcEntities); }; //添加 XscfSenparcEntities 依赖注入配置 services.AddScoped(databaseRegister.XscfDatabaseDbContextType, implementationFactory); //注册当前数据库的对象(必须) EntitySetKeys.TryLoadSetInfo(databaseRegister.XscfDatabaseDbContextType); //添加数据库相关注册过程 databaseRegister.AddXscfDatabaseModule(services); } return(services); }
//public ClientRepositoryBase() : this(null) { } public ClientRepositoryBase(INcfDbData db) : base(db) { //System.Web.HttpContext.Current.Response.Write("-"+this.GetType().Name + "<br />"); var keys = EntitySetKeys.GetAllEntitySetInfo(); _entitySetName = keys[typeof(T)].SetName; }
//public RepositoryBase() : // this(null) //{ //} public RepositoryBase(INcfDbData db) : base(db) { //System.Web.HttpContext.Current.Response.Write("-"+this.GetType().Name + "<br />"); //DB = db ?? ObjectFactory.GetInstance<INcfDbData>();//如果没有定义,取默认数据库 base.BaseDB = db; // ObjectFactory.GetInstance<INcfDbData>(); EntitySetKeysDictionary keys = EntitySetKeys.GetAllEntitySetInfo(); _entitySetName = keys[typeof(T)].SetName; }
public RepositoryBase(ISqlBaseFinanceData db) : base(db) { //System.Web.HttpContext.Current.Response.Write("-"+this.GetType().Name + "<br />"); //DB = db ?? ObjectFactory.GetInstance<ISqlClientFinanceData>();//如果没有定义,取默认数据库 base.BaseDB = db ?? SenparcDI.GetService <ISqlBaseFinanceData>();// ObjectFactory.GetInstance<ISqlClientFinanceData>(); EntitySetKeysDictionary keys = EntitySetKeys.GetEntitySetKeys(base.BaseDB.BaseDataContext.GetType()); _entitySetName = keys[typeof(T)]; }
public override async Task UninstallAsync(IServiceProvider serviceProvider, Func <Task> unsinstallFunc) { DatabaseToolkitEntities mySenparcEntities = serviceProvider.GetService <DatabaseToolkitEntities>(); //指定需要删除的数据实体 var dropTableKeys = EntitySetKeys.GetEntitySetInfo(this.XncfDatabaseDbContextType).Keys.ToArray(); //删除数据库表 await base.DropTablesAsync(serviceProvider, mySenparcEntities, dropTableKeys); await base.UninstallAsync(serviceProvider, unsinstallFunc).ConfigureAwait(false); }
/// <summary> /// 删除模块时需要执行的业务 /// </summary> /// <param name="serviceProvider"></param> /// <param name="unsinstallFunc"></param> /// <returns></returns> public override async Task UninstallAsync(IServiceProvider serviceProvider, Func <Task> unsinstallFunc) { MySenparcEntities mySenparcEntities = serviceProvider.GetService <MySenparcEntities>(); //指定需要删除的数据实体 //注意:这里作为演示,删除了所有的表,实际操作过程中,请谨慎操作,并且按照删除顺序对实体进行排序! var dropTableKeys = EntitySetKeys.GetEntitySetInfo(this.XscfDatabaseDbContextType).Keys.ToArray(); await base.DropTablesAsync(serviceProvider, mySenparcEntities, dropTableKeys); await unsinstallFunc().ConfigureAwait(false); }
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 override async Task UninstallAsync(IServiceProvider serviceProvider, Func <Task> unsinstallFunc) { var mySenparcEntitiesType = this.TryGetXncfDatabaseDbContextType; XncfBuilderEntities mySenparcEntities = serviceProvider.GetService(mySenparcEntitiesType) as XncfBuilderEntities; var xncfDbContextType = MultipleDatabasePool.Instance.GetXncfDbContextType(this.GetType()); //指定需要删除的数据实体 var dropTableKeys = EntitySetKeys.GetEntitySetInfo(xncfDbContextType).Keys.ToArray(); //删除数据库表 await base.DropTablesAsync(serviceProvider, mySenparcEntities, dropTableKeys); await base.UninstallAsync(serviceProvider, unsinstallFunc).ConfigureAwait(false); }
public void RunTest() { Console.WriteLine("XncfRegisterManager.RegisterList: " + XncfRegisterManager.RegisterList.Count); Assert.IsTrue(Senparc.Ncf.XncfBase.XncfRegisterManager.RegisterList.Count > 0); Console.WriteLine(XncfRegisterManager.RegisterList.Count); Assert.IsTrue(XncfRegisterManager.RegisterList.Count > 0); var allEntitySetInfo = EntitySetKeys.GetAllEntitySetInfo(); Console.WriteLine(allEntitySetInfo.Count); Assert.IsTrue(allEntitySetInfo.Count > 0); Console.WriteLine(allEntitySetInfo.ToJson(true)); Console.WriteLine("\r\n SenparcEntityTypes:"); Console.WriteLine(allEntitySetInfo.First().Value.SenparcEntityTypes.Select(z => z.Name).ToJson(true)); }
public void AddXscfDatabaseModule(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 Func <IServiceProvider, SenparcEntities> implementationFactory = s => new SenparcEntities(new DbContextOptionsBuilder <SenparcEntities>() .UseSqlServer(Scf.Core.Config.SenparcDatabaseConfigs.ClientConnectionString, b => base.DbContextOptionsAction(b, "Senparc.Web")) .Options); services.AddScoped(implementationFactory); services.AddScoped <ISenparcEntities>(implementationFactory); services.AddScoped <SenparcEntitiesBase>(implementationFactory); services.AddScoped(typeof(ISqlClientFinanceData), typeof(SqlClientFinanceData)); services.AddScoped(typeof(ISqlBaseFinanceData), typeof(SqlClientFinanceData)); //Attributes services.AddScoped(typeof(AuthenticationResultFilterAttribute)); services.AddScoped(typeof(AuthenticationAsyncPageFilterAttribute)); //预加载 EntitySetKey EntitySetKeys.TryLoadSetInfo(typeof(SenparcEntities)); //AutoMap映射 base.AddAutoMapMapping(profile => { profile.CreateMap <AdminUserInfo, CreateOrUpdate_AdminUserInfoDto>(); }); }
public override async Task UninstallAsync(IServiceProvider serviceProvider, Func <Task> unsinstallFunc) { #region 除数据库(演示) var mySenparcEntitiesType = this.TryGetXncfDatabaseDbContextType; MessageSenparcEntities mySenparcEntities = serviceProvider.GetService(mySenparcEntitiesType) as MessageSenparcEntities; //指定需要删除的数据实体 //注意:这里作为演示,在卸载模块的时候删除了所有本模块创建的表,实际操作过程中,请谨慎操作,并且按照删除顺序对实体进行排序! var dropTableKeys = EntitySetKeys.GetEntitySetInfo(this.TryGetXncfDatabaseDbContextType).Keys.ToArray(); await base.DropTablesAsync(serviceProvider, mySenparcEntities, dropTableKeys); #endregion await unsinstallFunc().ConfigureAwait(false); }
public void AddXscfDatabaseModule(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 //SenparcEntities 工厂配置 Func <IServiceProvider, SenparcEntities> senparcEntitiesImplementationFactory = s => new SenparcEntities(new DbContextOptionsBuilder <SenparcEntities>() .UseSqlServer(Scf.Core.Config.SenparcDatabaseConfigs.ClientConnectionString, b => base.DbContextOptionsAction(b, "Senparc.Service") /*从当前程序集读取*/) .Options); services.AddScoped(senparcEntitiesImplementationFactory); services.AddScoped <ISenparcEntities>(senparcEntitiesImplementationFactory); services.AddScoped <SenparcEntitiesBase>(senparcEntitiesImplementationFactory); //SystemServiceEntities 工厂配置(实际不会用到) Func <IServiceProvider, SystemServiceEntities> systemServiceEntitiesImplementationFactory = s => new SystemServiceEntities(new DbContextOptionsBuilder <SystemServiceEntities>() .UseSqlServer(Scf.Core.Config.SenparcDatabaseConfigs.ClientConnectionString, b => base.DbContextOptionsAction(b, "Senparc.Service") /*从当前程序集读取*/) .Options); services.AddScoped(systemServiceEntitiesImplementationFactory); services.AddScoped(typeof(ISqlClientFinanceData), typeof(SqlClientFinanceData)); services.AddScoped(typeof(ISqlBaseFinanceData), typeof(SqlClientFinanceData)); //预加载 EntitySetKey EntitySetKeys.TryLoadSetInfo(typeof(SenparcEntities)); }
public async Task UninstallAsync(IServiceProvider serviceProvider, Func <Task> unsinstallFunc) { //TODO:可以在基础模块里给出选项是否删除 WeixinSenparcEntities mySenparcEntities = serviceProvider.GetService <WeixinSenparcEntities>(); //指定需要删除的数据实体 //注意:这里作为演示,删除了所有的表,实际操作过程中,请谨慎操作,并且按照删除顺序对实体进行排序! var dropTableKeys = EntitySetKeys.GetEntitySetInfo(this.XscfDatabaseDbContextType).Keys.ToList(); //按照删除顺序排序 var types = new[] { typeof(UserTag_WeixinUser), typeof(UserTag), typeof(WeixinUser), typeof(MpAccount) }; types.ToList().AddRange(dropTableKeys); types = types.Distinct().ToArray(); await base.DropTablesAsync(serviceProvider, mySenparcEntities, types); await base.UninstallAsync(serviceProvider, unsinstallFunc).ConfigureAwait(false); }
public override async Task UninstallAsync(IServiceProvider serviceProvider, Func <Task> unsinstallFunc) { //TODO:可以在基础模块里给出选项是否删除 #region 除数据库(演示) var mySenparcEntitiesType = this.TryGetXncfDatabaseDbContextType; WeixinSenparcEntities mySenparcEntities = serviceProvider.GetService(mySenparcEntitiesType) as WeixinSenparcEntities; //指定需要删除的数据实体 //注意:这里作为演示,在卸载模块的时候删除了所有本模块创建的表,实际操作过程中,请谨慎操作,并且按照删除顺序对实体进行排序! var dropTableKeys = EntitySetKeys.GetEntitySetInfo(this.TryGetXncfDatabaseDbContextType).Keys.ToArray(); //按照删除顺序排序 var types = new[] { typeof(UserTag_WeixinUser), typeof(UserTag), typeof(WeixinUser), typeof(MpAccount) }; types.ToList().AddRange(dropTableKeys); types = types.Distinct().ToArray(); //指定需要删除的数据实体 await base.DropTablesAsync(serviceProvider, mySenparcEntities, types); #endregion await base.UninstallAsync(serviceProvider, unsinstallFunc).ConfigureAwait(false); }
/// <summary> /// 自动添加所有 XNCF 模块中标记了 [XncfAutoConfigurationMapping] 特性的对象 /// </summary> public static void ApplyAllAutoConfigurationMapping(ModelBuilder modelBuilder) { var entityTypeConfigurationMethod = typeof(ModelBuilder).GetMethods() .FirstOrDefault(z => z.Name == "ApplyConfiguration" && z.ContainsGenericParameters && z.GetParameters().SingleOrDefault()?.ParameterType.GetGenericTypeDefinition() == typeof(IEntityTypeConfiguration <>)); //所有模块中数据库实体中自动获取所有的 DbSet 下的实体类型 //TODO:筛选基础类中的 var xncfDatabaseDbContextList = MultipleDatabasePool.Instance.Values.SelectMany(z => z.Values); //TODO:为了进一步提高效率,可以对同一个 DbContext 的子类去重 foreach (var xncfDatabaseDbContextType in xncfDatabaseDbContextList) { var setKeyInfoList = EntitySetKeys.GetEntitySetInfo(xncfDatabaseDbContextType).Values; foreach (var setKeyInfo in setKeyInfoList) { //数据库实体类型 var entityType = setKeyInfo.DbSetType; if (AddedApplyedAutoConfigurationMappingEntityTypes.Contains(entityType)) { //Console.WriteLine($"\t [{xncfDatabaseDbContextType.Name}]ApplyAllAutoConfigurationMapping 有重复 setKeyInfo:{entityType.Name},已跳过"); continue; } //Console.WriteLine($"\t [{xncfDatabaseDbContextType.Name}]ApplyAllAutoConfigurationMapping 处理 setKeyInfo:{entityType.Name}"); //默认空 ConfigurationMapping 对象的泛型类型 var blankEntityTypeConfigurationType = typeof(BlankEntityTypeConfiguration <>).MakeGenericType(entityType); //创建一个新的实例 var blankEntityTypeConfiguration = Activator.CreateInstance(blankEntityTypeConfigurationType); //最佳到末尾,这样可以优先执行用户自定义的代码 XncfAutoConfigurationMappingList.Add(blankEntityTypeConfiguration); AddedApplyedAutoConfigurationMappingEntityTypes.Add(entityType); } } foreach (var autoConfigurationMapping in XncfAutoConfigurationMappingList) { if (autoConfigurationMapping == null) { continue; } SenparcTrace.SendCustomLog("监测到 ApplyAllAutoConfigurationMapping 执行", autoConfigurationMapping.GetType().FullName); //获取配置实体类型,如:DbConfig_WeixinUserConfigurationMapping Type mappintConfigType = autoConfigurationMapping.GetType(); //获取 IEntityTypeConfiguration<Entity> 接口 var interfaceType = mappintConfigType.GetInterfaces().FirstOrDefault(z => z.Name.StartsWith("IEntityTypeConfiguration")); if (interfaceType == null) { continue; } //实体类型,如:DbConfig Type entityType = interfaceType.GenericTypeArguments[0]; //PS:此处不能过滤,否则可能导致如 SystemServiceEntities_SqlServer / SystemServiceEntities_Mysql 中只有先注册的对象才成功,后面的被忽略 //if (ApplyedAutoConfigurationMappingTypes.Contains(entityType)) //{ // //如果已经添加过则跳过。作此判断因为:原始的 XncfAutoConfigurationMappingList 数据可能和上一步自动添加 DataSet 中的对象有重复 // //continue; //} entityTypeConfigurationMethod.MakeGenericMethod(entityType) .Invoke(modelBuilder, new object[1] { autoConfigurationMapping }); ApplyedAutoConfigurationMappingTypes.Add(entityType); //entityTypeConfigurationMethod.Invoke(modelBuilder, new[] { autoConfigurationMapping }); } //TODO:添加 IQueryTypeConfiguration<> }
public static void AddNcfServices(this IServiceCollection services, IConfiguration configuration, IWebHostEnvironment env, CompatibilityVersion compatibilityVersion) { //如果运行在IIS中,需要添加IIS配置 //https://docs.microsoft.com/zh-cn/aspnet/core/host-and-deploy/iis/index?view=aspnetcore-2.1&tabs=aspnetcore2x#supported-operating-systems //services.Configure<IISOptions>(options => //{ // options.ForwardClientCertificate = false; //}); //启用以下代码强制使用 https 访问 //services.AddHttpsRedirection(options => //{ // options.RedirectStatusCode = StatusCodes.Status307TemporaryRedirect; // options.HttpsPort = 443; //}); //读取Log配置文件 var repository = LogManager.CreateRepository("NETCoreRepository"); XmlConfigurator.Configure(repository, new FileInfo("log4net.config")); //提供网站根目录 if (env.ContentRootPath != null) { SiteConfig.ApplicationPath = env.ContentRootPath; SiteConfig.WebRootPath = env.WebRootPath; } services.Configure <CookiePolicyOptions>(options => { // This lambda determines whether user consent for non-essential cookies is needed for a given request. options.CheckConsentNeeded = context => true; options.MinimumSameSitePolicy = SameSiteMode.None; }); //services.AddMvc(options => //{ // //options.Filters.Add<HttpGlobalExceptionFilter>(); //}) //.SetCompatibilityVersion(compatibilityVersion) //.AddRazorPagesOptions(options => //{ // //options.AllowAreas = true;//支持 Area // //options.AllowMappingHeadRequestsToGetHandler = false;//https://www.learnrazorpages.com/razor-pages/handler-methods //}) services.AddMultiTenant(); //注册多租户(按需) EntitySetKeys.TryLoadSetInfo(typeof(SenparcEntitiesMultiTenant)); //注册多租户数据库的对象(按需) services.AddScoped <ITenantInfoDbData, TenantInfoDbData>(); services.AddScoped <TenantInfoRepository>(); services.AddScoped <IClientRepositoryBase <TenantInfo>, TenantInfoRepository>(); services.AddSenparcGlobalServices(configuration);//注册 CO2NET 基础引擎所需服务 var builder = services.AddRazorPages(opt => { //opt.RootDirectory = "/"; }) .AddNcfAreas(env)//注册所有 Ncf 的 Area 模块(必须) .ConfigureApiBehaviorOptions(options => { options.InvalidModelStateResponseFactory = actionContext => { var values = actionContext.ModelState.Where(_ => _.Value.ValidationState == Microsoft.AspNetCore.Mvc.ModelBinding.ModelValidationState.Invalid).Select(_ => new { _.Key, Errors = _.Value.Errors.Select(__ => __.ErrorMessage) }); AjaxReturnModel commonReturnModel = new AjaxReturnModel <object>(values); commonReturnModel.Success = false; commonReturnModel.Msg = "参数校验未通过"; //commonReturnModel.StatusCode = Core.App.CommonReturnStatusCode.参数校验不通过; return(new BadRequestObjectResult(commonReturnModel)); }; }) .AddXmlSerializerFormatters() .AddJsonOptions(options => { //忽略循环引用 //options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; //不使用驼峰样式的key //options.SerializerSettings.ContractResolver = new DefaultContractResolver(); //设置时间格式 //options.SerializerSettings.DateFormatString = "yyyy-MM-dd"; }) //https://docs.microsoft.com/en-us/aspnet/core/fundamentals/app-state?view=aspnetcore-2.1&tabs=aspnetcore2x //.AddSessionStateTempDataProvider() //忽略JSON序列化过程中的循环引用:https://stackoverflow.com/questions/7397207/json-net-error-self-referencing-loop-detected-for-type .AddRazorPagesOptions(options => { //自动注册 防止跨站请求伪造(XSRF/CSRF)攻击 options.Conventions.Add(new Core.Conventions.AutoValidateAntiForgeryTokenModelConvention()); }); #if DEBUG //Razor启用运行时编译,多个项目不需要手动编译。 if (env.IsDevelopment()) { builder.AddRazorRuntimeCompilation(options => { //自动索引所有需要使用 RazorRuntimeCompilation 的模块 foreach (var razorRegister in XncfRegisterManager.RegisterList.Where(z => z is IXncfRazorRuntimeCompilation)) { try { var libraryPath = ((IXncfRazorRuntimeCompilation)razorRegister).LibraryPath; options.FileProviders.Add(new PhysicalFileProvider(libraryPath)); } catch (Exception ex) { SenparcTrace.BaseExceptionLog(ex); } } }); } #endif //TODO:在模块中注册 services.AddScoped <Ncf.AreaBase.Admin.Filters.AuthenticationResultFilterAttribute>(); //支持 Session services.AddSession(); //解决中文进行编码问题 services.AddSingleton(HtmlEncoder.Create(UnicodeRanges.All)); //使用内存缓存 services.AddMemoryCache(); //注册 SignalR services.AddSignalR(); //注册 Lazy<T> services.AddTransient(typeof(Lazy <>)); services.Configure <SenparcCoreSetting>(configuration.GetSection("SenparcCoreSetting")); services.Configure <SenparcSmsSetting>(configuration.GetSection("SenparcSmsSetting")); //自动依赖注入扫描 services.ScanAssamblesForAutoDI(); //已经添加完所有程序集自动扫描的委托,立即执行扫描(必须) AssembleScanHelper.RunScan(); //services.AddSingleton<Core.Cache.RedisProvider.IRedisProvider, Core.Cache.RedisProvider.StackExchangeRedisProvider>(); ////添加多租户 //services.AddMultiTenant(); //注册 User 登录策略 services.AddAuthorization(options => { options.AddPolicy("UserAnonymous", policy => { policy.RequireClaim("UserMember"); }); }); services.AddHttpContextAccessor(); //Repository & Service services.AddScoped <ISysButtonRespository, SysButtonRespository>(); //Other services.AddScoped <IAdminWorkContextProvider, AdminWorkContextProvider>(); services.AddTransient <IActionContextAccessor, ActionContextAccessor>(); //忽略某些 API //Senparc.CO2NET.WebApi.Register.OmitCategoryList.Add(Senparc.NeuChar.PlatformType.WeChat_Work.ToString()); //Senparc.CO2NET.WebApi.Register.OmitCategoryList.Add(Senparc.NeuChar.PlatformType.WeChat_MiniProgram.ToString()); //Senparc.CO2NET.WebApi.Register.OmitCategoryList.Add(Senparc.NeuChar.PlatformType.WeChat_Open.ToString()); //Senparc.CO2NET.WebApi.Register.OmitCategoryList.Add(Senparc.NeuChar.PlatformType.WeChat_OfficialAccount.ToString()); //激活 Xncf 扩展引擎(必须) services.StartEngine(configuration); }
/// <summary> /// 自动添加所有 XNCF 模块中标记了 [XncfAutoConfigurationMapping] 特性的对象 /// </summary> public static void ApplyAllAutoConfigurationMapping(ModelBuilder modelBuilder) { var entityTypeConfigurationMethod = typeof(ModelBuilder).GetMethods() .FirstOrDefault(z => z.Name == "ApplyConfiguration" && z.ContainsGenericParameters && z.GetParameters().SingleOrDefault()?.ParameterType.GetGenericTypeDefinition() == typeof(IEntityTypeConfiguration <>)); //所有模块中数据库实体中自动获取所有的 DbSet 下的实体类型 foreach (var databaseRegister in Register.XncfDatabaseList) { if (databaseRegister.XncfDatabaseDbContextType != null) { var setKeyInfoList = EntitySetKeys.GetEntitySetInfo(databaseRegister.XncfDatabaseDbContextType).Values; foreach (var setKeyInfo in setKeyInfoList) { //数据库实体类型 var entityType = setKeyInfo.DbSetType; //默认空 ConfigurationMapping 对象的泛型类型 var blankEntityTypeConfigurationType = typeof(BlankEntityTypeConfiguration <>).MakeGenericType(entityType); //创建一个新的实例 var blankEntityTypeConfiguration = Activator.CreateInstance(blankEntityTypeConfigurationType); //最佳到末尾,这样可以优先执行用户自定义的代码 XncfAutoConfigurationMappingList.Add(blankEntityTypeConfiguration); } } } foreach (var autoConfigurationMapping in XncfAutoConfigurationMappingList) { if (autoConfigurationMapping == null) { continue; } SenparcTrace.SendCustomLog("监测到 ApplyAllAutoConfigurationMapping 执行", autoConfigurationMapping.GetType().FullName); //获取配置实体类型,如:DbConfig_WeixinUserConfigurationMapping Type mappintConfigType = autoConfigurationMapping.GetType(); //获取 IEntityTypeConfiguration<Entity> 接口 var interfaceType = mappintConfigType.GetInterfaces().FirstOrDefault(z => z.Name.StartsWith("IEntityTypeConfiguration")); if (interfaceType == null) { continue; } //实体类型,如:DbConfig Type entityType = interfaceType.GenericTypeArguments[0]; if (ApplyedAutoConfigurationMappingTypes.Contains(entityType)) { continue;//如果已经添加过则跳过。作此判断因为:原始的 XncfAutoConfigurationMappingList 数据可能和上一步自动添加 DataSet 中的对象有重复 } entityTypeConfigurationMethod.MakeGenericMethod(entityType) .Invoke(modelBuilder, new object[1] { autoConfigurationMapping }); ApplyedAutoConfigurationMappingTypes.Add(entityType); //entityTypeConfigurationMethod.Invoke(modelBuilder, new[] { autoConfigurationMapping }); } //TODO:添加 IQueryTypeConfiguration<> }
/// <summary> /// 添加模块 /// </summary> /// <param name="services"></param> /// <param name="configuration"></param> /// <returns></returns> public virtual IServiceCollection AddXncfModule(IServiceCollection services, IConfiguration configuration) { if (this is IXncfDatabase databaseRegister) { //遍历所有Register中的数据库进行注册 if (XncfDatabaseDbContextPool.Instance.ContainsKey(this.GetType())) { var dbContextTypes = XncfDatabaseDbContextPool.Instance[this.GetType()]; foreach (var dbContextType in dbContextTypes.Values) { var dbOptionBuilderType = dbContextType.GetConstructors() .First().GetParameters().First().ParameterType; //定义 XncfSenparcEntities 实例生成 Func <IServiceProvider, DbContext> implementationFactory = s => { DbContextOptionsBuilder dbOptionBuilder; 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 currentDatabaseConfiguration = DatabaseConfigurationFactory.Instance.Current; //使用数据库 currentDatabaseConfiguration.UseDatabase(dbOptionBuilder, Ncf.Core.Config.SenparcDatabaseConnectionConfigs.ClientConnectionString, new XncfDatabaseData(databaseRegister, null /*默认使用当前 Register 程序集*/), (b, xncfDatabaseData) => { ////进行附加配置 //this.DbContextOptionsAction?.Invoke(b); //执行 DatabaseConfiguration 中的 DbContextOptionsActionBase,进行基础配置; currentDatabaseConfiguration.DbContextOptionsActionBase(b, xncfDatabaseData); //其他需要进行的配置,如对于 SQL Server: //b.EnableRetryOnFailure( // maxRetryCount: 5, // maxRetryDelay: TimeSpan.FromSeconds(5), // errorNumbersToAdd: new int[] { 2 }); }); //创建 SenparcEntities 实例 var xncfSenparcEntities = Activator.CreateInstance(dbContextType, dbOptionBuilder.Options); return(xncfSenparcEntities as DbContext); }; //添加 XncfSenparcEntities 依赖注入配置 services.AddScoped(dbContextType, implementationFactory); //注册当前数据库的对象(必须) EntitySetKeys.TryLoadSetInfo(dbContextType); } } else { var errMsg = $"{databaseRegister.GetType().FullName} 未注册任何数据库 DbContext!"; SenparcTrace.BaseExceptionLog(new NcfDatabaseException(errMsg, null, null)); Console.WriteLine(errMsg); } //添加数据库相关注册过程 databaseRegister.AddXncfDatabaseModule(services); } return(services); }