Пример #1
0
        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;
        }
Пример #4
0
        //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;
        }
Пример #5
0
        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)];
        }
Пример #6
0
        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);
        }
Пример #7
0
        /// <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);
        }
Пример #8
0
        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));
        }
Пример #9
0
        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);
        }
Пример #10
0
        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));
        }
Пример #11
0
        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>();
            });
        }
Пример #12
0
        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);
        }
Пример #13
0
        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);
        }
Пример #15
0
        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);
        }
Пример #16
0
        /// <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<>
        }
Пример #17
0
        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);
        }
Пример #18
0
        /// <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<>
        }
Пример #19
0
        /// <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);
        }