第四节 数据库启动配置

以上章节讲述的那么多,但依然没有我们最为关心的对数据库的操作,不管什么样的网站最后它们所提交的数据都要被持久化的数据库中。实际上对于国内的大多数开发者来说,在进行与数据库交互的程序开发时更加关注于数据层和所实现功能,对它们的对它们所进行的代码优化和重构所花费的资源也相对较多(本人也是这样)。通过nopCommerce_4.10应用程序的源代码属性国外的开发数据者相对来说更加关注于整个程序的调用或者执行逻辑以及公用的底层实现,这在Core项目中存在大量的公用实现和实例定义,以及通过大量的类来定义和实现上述章节中的定义和配置,这对国内的开发者来说是不可想象和不能被理解的,我们只需要在默认的Startup类中通过一些简单的执行语句和在Web项目中对appsettings.json文件作一些简单的配置,完全可以实现上述章节所要实现的功能,这些现实存在使我在接近nopCommerce_4.10开发者思路方法找到了方向和重点。两者开发思想在程序开发中只存在选择不存在高低,而前者更方便国内开发者的理解和使用习惯,后者可能更加符合nopCommerce_4.10应用程序开发者的开发思维和开发习惯,而我现在所从事的是对nopCommerce_4.10应用程序进行反向开发,所以本人要的思维现在要更加靠近第二种思想,虽然本人很不习惯和舒服,但是也必须这样做,只能这样才能在对nopCommerce_4.10应用程序的反向开发中走的更加顺利、更加的远。

一、定义SettingController类

1、在Controllers项目中新建类:SettingController,添加引用项目Core和Service,同时在SettingController.cs中声明引用:using Core.Domain.Configuration; using Service.Configuration;最终SettingController类的定义如下:

#region Ctor

        public SettingController(

            ISettingService settingService)

        {

            this._settingService = settingService;

        }

        #endregion

 

        #region Fields

        private readonly ISettingService _settingService;

        #endregion

 

        public IActionResult Create()

        {

            return View();

        }

 

        [HttpPost]

        [ValidateAntiForgeryToken]

        public IActionResult Create(Setting model)

        {

            return View();

      }

2、在Web项目中的Web文件夹下新建Setting文件夹

3、新建Setting.Create视图,其具体操作见图1-5

图1-5

 

4、修改更改Startup.cs文件中的默认方法public void Configure(IApplicationBuilder app, IHostingEnvironment env)方法为:

        /// <summary>

        /// 【配置】

        /// <param name="app">用于配置应用程序请求管道的生成器实例。</param>

        /// <remarks>

        /// 摘要:

        ///    此方法由运行时调用,使用此方法配置HTTP请求管道。

        /// </remarks>

        /// </summary>

        public void Configure(IApplicationBuilder app)

        {

            app.UseMvc(routes =>

            {

                routes.MapRoute(

                    name: "default",

                    template: "{controller=Setting}/{action=Create}/{id?}");

            });

        }

5、这时整个程序构建如图1-6

图1-6

6、按F5发现能够正常启动默认的Setting.Create页面。

7、如果把定义在Framework.Infrastructure.DependencyRegistrarRegister方法中的builder.RegisterType<SettingService>().As<ISettingService>().InstancePerLifetimeScope();注释掉,按F5启动后发现程序执行到了:HTTP 500页面。如果再把SettingController.cs文件中的拷贝构造方法注释掉:

/*

        #region Ctor

 

        public SettingController(

            ISettingService settingService)

        {

            this._settingService = settingService;

        }

 

        #endregion

        */

按F5依然能够正常启动默认的Setting.Create页面,这是只要在程序中因为拷贝构造方法通过使用Autofac中间件调用类的接口调用类实现对该类的实例化,就必须对该类及其接口进行依赖注册(MEF中间件就比较简单,不必进行对类及其接口进行显式的注册定义,只需要在对类及其接口的定义上声明两个相对应的过滤器就能实现Autofac中间件上述所实现的功能),才能保障整个程序的正常启动。

​​​​​​​二、数据启动配置

nopCommerce_4.10应用程序是通过对数据启动进行配置,作为其实现与数据库交互链接的开始,这也的使用Autofac中间件所造成的必然,因为只要调用其接口必须进行显式的注册定义(只是实现的类的定义和调用逻辑有单间也有复杂,而nopCommerce_4.10应用程序显然是后者)。去除步骤7中的注释,回到步骤6,nopCommerce_4.10应用程序是怎样实现与数据库的交互链接的,其实现方法和调用逻辑如何,我将详细的做以下的剖析。

  1. 添加Core.Data.IRepository接口的定义,实际上该接口被Data项目中的EfRepository类继承并实现(注意:我认IRepository接口的定义最好与EfRepository类同时定义在Data项目中,显然nopCommerce_4.10并没这样作,如果有间通过重构把它们一块定义到Data项目,看看整个应用程序的调用逻辑是否显的更加的清晰、明了)

  2. 添加Data项目通过NuGet为该项目引用“Microsoft.EntityFrameworkCore.SqlServer”,引用Core项目, 在其项目中添加EfRepository类、NopObjectContext类和IdbContext接口定义。这时整个程序构建如图1-7

如图1-7

3、为Service.Configuration.SettingService添加拷贝构造方法及其相应的变量如下:

#region 构造方法

        /// <summary>

        /// 【拷贝构造方法】

        /// <remarks>

        /// 摘要:

        ///    对该类中的一些对象的实例,进行初始化操作。

        /// </remarks>

        /// </summary>

        public SettingService(IRepository<Setting> settingRepository)

        {

            this._settingRepository = settingRepository;

        }

        #endregion

 

        #region 变量--私有/保护

        /// <summary>

        /// 【事件发布器实例】

        /// <remarks>

        /// 摘要:

        ///    该变量只被声明,并未被立即初始化,它的初始化操作在拷贝构造方法中。

        /// </remarks>

        /// </summary>

        private readonly IRepository<Setting> _settingRepository;

#endregion

 

4、为Framework项目,添加Data项目的引用,同时在Framework.Infrastructure.Extensions.ServiceCollectionExtensions类中添加引用“using Data;”,

在Framework.Infrastructure.DependencyRegistrar类的Register方法中定义语句:

builder.Register(context => new NopObjectContext(context.Resolve<DbContextOptions<NopObjectContext>>())).As<IDbContext>().InstancePerLifetimeScope();

            //仓储。

builder.RegisterGeneric(typeof(EfRepository<>)).As(typeof(IRepository<>)).InstancePerLifetimeScope();

同时添加添加引用“using Data;”。

但在语句builder.Register(context => new NopObjectContext(context.Resolve<DbContextOptions<NopObjectContext>>())).As<IDbContext>().InstancePerLifetimeScope();中所使用context.Resolve中的ResolveAutofac.ResolutionExtensions中的默认方法,在IEngine接口及其继承实现类NopEngine中nopCommerce_4.10应用程序自定义了三关于个Resolve的方法,具体实现见源代码,“MyNopCommerce(不删,003_数据库启动配置)”。

通过实际操作可以发现如果不在IEngine接口及其继承实现类NopEngine中定义三关于个Resolve的方法,而使用Autofac.ResolutionExtensions中的默认方法,按F5发现能够正常启动默认的Setting.Create页面,甚至也可以把Setting.Create页面中的数据提交到数据库中。如果在IEngine接口及其继承实现类NopEngine中定义三关于个Resolve的方法,则在按F5执行程序时会在builder.Register(context => new NopObjectContext(context.Resolve<DbContextOptions<NopObjectContext>>())).As<IDbContext>().InstancePerLifetimeScope();语句处发生异常:“Autofac.Core.Registration.ComponentNotRegisteredException:The requested service 'Microsoft.EntityFrameworkCore.DbContextOptions`1[[Data.NopObjectContext, Data, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' has not been registered. To avoid this exception, either register a component to provide the service, check for service registration using IsRegistered(), or use the ResolveOptional() method to resolve an optional dependency.”。虽然我到至今为止还不知道nopCommerce_4.10的开发自定的三关于个Resolve的方法有除了产生上述异常外还有其它的什么作用,但依然在我的程序中下定义了它们。另外而要注意的是第三步中的拷贝构造方法必须被定义,否则也不会出现上述异常。

5造成上述异常的因素是我没有在程序中实现数据启动配置的定义,而Framework.Infrastructure.NopDbStartup即是实现数据启动配置定义的类,我们会发现NopDbStartup类也是继承并实现了INopStartup接口,实际上在nopCommerce_4.10应用程序中继承并实现InopStartup接口的类共有8个,但是在最简实现中,如果想要实现把前台数据提交到数据库中NopMvcStartup和NopDbStartupnopCommerce_4.10应用程序实现该功能的两个必不可少的类。NopDbStartupConfigureServices方法中调用了AddNopObjectContext方法。

而AddNopObjectContext方法定义在Framework.Infrastructure.Extensions.ServiceCollectionExtensions类中具体实现如下:

/// <summary>

        /// 【添加Nop对象上下文】

        /// <param name="services">服务集合实例。</param>

        /// <returns>

        /// 返回:

        ///     返回,Mvc生成器实例。

        /// </returns>

        /// <remarks>

        /// 摘要:

        ///     注册Data.NopObjectContext对象。

        /// </remarks>

        /// </summary>

        public static void AddNopObjectContext(this IServiceCollection services)

        {

            services.AddDbContext<NopObjectContext>(optionsBuilder =>

            {

                 //optionsBuilder.UseSqlServerWithLazyLoading(services);

            });

}

先注释掉语句//optionsBuilder.UseSqlServerWithLazyLoading(services);因为它的存在会分散我们的关注的心,但是又要很快的用到它。

6、从上面的AddNopObjectContext方法的下定义可以看出它调用NopObjectContext类,NopObjectContext类则是定义在Data项目中,此项目中即是nopCommerce_4.10应用程序的数据层,其中所定义的方法和类是与数据库操作相关的。到此我们终于可以看到nopCommerce_4.10应用程序在纵向操作将结束的曙光了。

7、这时按F5发现能够正常启动默认的Setting.Create页面,说明异常已经排除。到此为止我已经详细的剖析了nopCommerce_4.10应用程序是如何实现和定义数据启动配置的,至于更新详细的信息请见我所上传代码“MyNopCommerce(不删,003_数据库启动配置) (https://download.csdn.net/download/zhoujian_911/10712135)”中的“日志”与“.vsdx”文件。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值