Asp.Net Core中创建多DbContext并迁移到数据库的步骤

  在我们的项目中我们有时候需要在我们的项目中创建DbContext,而且这些DbContext之间有明显的界限,比如系统中两个DbContext一个是和整个数据库的权限相关的内容而另外一个DbContext则主要是和具体业务相关的内容,这两个部分彼此之间可以分开,那么这个时候我们就可以在我们的项目中创建两个不同的DbContext,然后分别注入进去,当然这两个DbContext可以共用一个ConnectionString,也可以分别使用不同的DbContext,这个需要根据不同的需要来确定,在我们建立完了不同的DbContext的时候,我们就需要分别将每一个DbContext修改的内容迁移到数据库里面去,这个就涉及到数据库Migration的问题了,所以整篇文章主要围绕如何创建多个DbContext和每个DbContext的Migration的问题。 

  下面我们通过代码来创建两个不同的DbContext

  1 创建AuthorityDbContext

public class AuthorityDbContext : AbpZeroDbContext<Tenant, Role, User, AuthorityDbContext> {
        /* Define a DbSet for each entity of the application */
 
        public DbSet<UserMapping> UserMappings { get; set; }
 
        public SunlightDbContext(DbContextOptions<SunlightDbContext> options)
            : base(options) {
        }
 
        protected override void OnModelCreating(ModelBuilder modelBuilder) {
            base.OnModelCreating(modelBuilder);
            modelBuilder.ApplyConfiguration(new TenantConfiguration());
 
            // 请在此处填写所有与具体数据库无关的 Model 调整,确保单元测试可以覆盖
 
            if (Database.IsInMemory())
                return;           
        }
        
    }

  这个DbContext主要用来做一些和身份验证以及权限相关的操作,这里只是定义了一个最简单的结构,后面的一个DbContext就是具体业务相关的内容,在我们的项目中,我们两个DbContext会使用相同的连接字符串。

  2 IDesignTimeDbContextFactory接口实现

/// <summary>
   /// 用于 EF Core Migration 时创建 DbContext,数据库连接信息来自 XXX.Dcs.WebHost 项目 appsettings.json
   /// </summary>
   public class AuthorityDesignTimeDbContextFactory : IDesignTimeDbContextFactory<AuthorityDbContext> {
       private const string DefaultConnectionStringName = "Default";
 
       public SunlightDbContext CreateDbContext(string[] args) {
           var configuration = AppConfigurations.Get(WebContentDirectoryFinder.CalculateContentRootFolder());
           var connectString = configuration.GetConnectionString(DefaultConnectionStringName);
 
           var builder = new DbContextOptionsBuilder<SunlightDbContext>();
           builder.UseSqlServer(connectString);
           return new SunlightDbContext(builder.Options);
       }
   }

  在了解这段代码之前,你可以先了解一下这个到底是做什么用的,就像注释里面说的,当我们使用EFCore Migration的时候,这里会默认读取WebHost项目里面的appsettings.json里面的Default配置的连接字符串。

{
  "ConnectionStrings": {
    "Default": "Server=XXXX,XX;Database=XXXX;User Id=XXXX;Password=XXXX;",
    "DcsEntity": "Server=XXXX,XX;Database=XXXX;User Id=XXXX;Password=XXXX;"
  },
  "Redis": {
    "Configuration": "127.0.0.1:XXXX",
    "InstanceName": "XXXX-Sales"
  },
  "App": {
    "ServerRootAddress": "http://localhost:XXXX/",
    "ClientRootAddress": "http://localhost:XXXX/",
    "CorsOrigins": "http://localhost:XX,http://localhost:XX,http://localhost:XX"
  },
  "Kafka": {
    "BootstrapServers": "127.0.0.1:XX",
    "MessageTimeoutMs": 5000,
    "Topics": {
      "CustomerAndVehicleEvent": "XXXX-customer-update",
      "AddOrUpdateProductCategoryEvent": "XXXX-add-update-product-category",
      "AddOrUpdateDealerEvent": "XXXX-add-update-dealer",
      "ProductUpdateEvent": "XXXX-product-update",
      "VehicleInformationUpdateStatusEvent": "XXXX-add-update-vehicle-info",
      "AddCustomerEvent": "cowin-add-customer"
    }
  },
  "Application": {
    "Name": "XXXX-sales"
  },
  "AppSettings": {
    "ProductSyncPeriodMi": 60,
    "DealerSyncPeriodMi": 60
  },
  "Eai": {
    "Authentication": {
      "Username": "2XXX2",
      "Password": "XXXX"
    },
    "Services": {
      "SapFinancial": "http://XXXX:XXXX/OSB_MNGT/Proxy/XXXX"
    }
  },
  "DependencyServices": {
    "BlobStorage": "http://XXXX-XXXX/"
  },
  "Authentication": {
    "JwtBearer": {
      "IsEnabled": true,
      "Authority": "http://XXXX/",
      "RequireHttpsMetadata": false
    }
  },
  "Sentry": {
    "IncludeRequestPayload": true,
    "SendDefaultPii": true,
    "MinimumBreadcrumbLevel": "Debug",
    "MinimumEventLevel": "Warning",
    "AttachStackTrace": true
  },
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  }
}

  3 DB Migration

  有了上面的工作之后,我们就能够进行数据库迁移并更新到数据库了,主要过程分为2步Add-Migration XXX和Update-Database -verbose两步,只不过是现在我们想构建多个DbContext,所以我们需要通过参数-c xxxDbContext来指定具体的DbContext ,否则会报下面的错误。More than one DbContext was found. Specify which one to use. Use the '-Context' parameter for PowerShell commands and the '--context' parameter for dotnet commands.

  有了这些以后,我们就可以更新到数据库了,在更新的时候记住要指定DbContext,更新时使用下面的命令:Update-Database -verbose -c XXXDbContext。

  4 创建第二个DbContext

  有了前面的过程,创建第二个DbContext的过程就比较简单了,重复上面的步骤一、二、三,然后完成第二个DbContext的创建和数据库的迁移,但是这里我们需要注意一些不同之处,第一个由于我们想要使用ABP框架中的多租户相关的一些实体,所以这里我们构建的基类是继承自AbpZeroDbContext,后面我们创建的业务相关的DbContext的时候,我们不需要这些,所以我们只需简单继承自AbpDbContext即可。

  5 Startup中初始化EF Core DbContext

  这个和之前创建一个DbContext有所不同的是我们需要向Asp.Net Core依赖注入容器中两次注入不同的DbContext,在Asp.Net Core中该如何创建DbContext并实现注入,请点击这里参考官方文档,在这里我们需要在Startup中的ConfigureServices中调用下面的代码,这个是有所不同的地方,具体我们来看看代码。

// 初始化 EF Core DbContext
            var abpConnectionString = _appConfiguration.GetConnectionString("Default");
            services.AddDbContext<SunlightDbContext>(options => {
                options.UseSqlServer(abpConnectionString);
                if (Environment.IsDevelopment()) {
                    options.EnableSensitiveDataLogging();
                    // https://docs.microsoft.com/en-us/ef/core/querying/client-eval#optional-behavior-throw-an-exception-for-client-evaluation
                    options.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning));
                }
            });
            // AuthConfigurer.MapUserIdentity 需使用 DbContextOptions<SunlightDbContext>
            // Abp DI 未自动注册该对象,故而特别处理
            services.AddTransient(provider => {
                var builder = new DbContextOptionsBuilder<SunlightDbContext>();
                builder.UseSqlServer(abpConnectionString);
                return builder.Options;
            });
            var dcsConnectionString = _appConfiguration.GetConnectionString("DcsEntity");
            services.AddDbContext<DcsDbContext>(options => {
                options.UseSqlServer(dcsConnectionString);
                if (Environment.IsDevelopment()) {
                    options.EnableSensitiveDataLogging();
                    // https://docs.microsoft.com/en-us/ef/core/querying/client-eval#optional-behavior-throw-an-exception-for-client-evaluation
                    options.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning));
                }
            }); 

  这样就能够在服务具体运行的过程中来添加具体的DbContext啦,经过上面的过程我们就能够实现在一个项目中添加多个DbContext,并迁移数据库整个过程。

以上就是Asp.Net Core中创建多DbContext并迁移到数据库的步骤的详细内容,更多关于Asp.Net Core创建多DbContext并迁移到数据库的资料请关注我们其它相关文章!

(0)

相关推荐

  • ASP.NET Core WebApi版本控制的实现

    前言: 在日常项目开发中,随着项目需求不断的累加.不断的迭代:项目服务接口需要向下兼容历史版本:前些时候就因为Api接口为做版本管理导致接口对低版本兼容处理不友好. 最近就像了解下如何实现WebApi版本控制,那么版本控制有什么好处呢? WebApi版本控制的好处 有助于及时推出功能, 而不会破坏现有系统,兼容性处理更友好. 它还可以帮助为选定的客户提供额外的功能. 接下来就来实现版本控制以及在Swagger UI中接入WebApi版本 一.WebApi版本控制实现 通过Microsoft.As

  • 详解如何在ASP.NET Core中使用Route特性

    ASP.NET Core 中的 Route 中间件的职责在于将 request 匹配到各自 Route 处理程序上,Route 分两种:基于约定 和 基本特性 模式. 基于约定 模式的Route采用集中化的方式,而 基于特性 的方式允许你在 Action 或者 Controller 上单独定义,到底采用哪一种可以基于你自己的应用场景,本篇就来讨论如何使用 基于特性 模式. 创建 Controller 类 创建一个 DefaultController 类,新增如下代码. public class

  • 详解如何在ASP.NET Core中编写高效的控制器

    通过遵循最佳实践,可以编写更好的控制器.所谓的"瘦"控制器(指代码更少.职责更少的控制器)更容易阅读和维护.而且,一旦你的控制器很瘦,可能就不需要对它们进行太多测试了.相反,你可以专注于测试业务逻辑和数据访问代码.瘦控制器的另一个优点是,它更容易维护控制器的多个版本. 这篇文章讨论了使控制器变胖的坏习惯,然后探索了使控制器变瘦和易于管理的方法.我列出编写控制器的最佳实践可能并不全面,但我已经讨论了最重要的一些,并在适当的情况下提供了相关的源代码.在接下来的几节中,我们将研究什么是胖控制

  • 详解如何在ASP.NET Core中使用IHttpClientFactory

    利用IHttpClientFactory可以无缝创建HttpClient实例,避免手动管理它们的生命周期. 当使用ASP.Net Core开发应用程序时,可能经常需要通过HttpClient调用WebAPI的方法以检查终结点是否正常工作.要实现这一点,通常需要实例化HttpClient并使用该实例来调用你的方法.但是直接使用HttpClient也有一些缺点,主要与手动管理实例的生命周期有关. 你可以使用IHttpClientFactory创建HttpClient来避免这些问题.IHttpClie

  • 详解如何在ASP.NET Core Web API中以三种方式返回数据

    在 ASP.NET Core 中有三种返回 数据 和 HTTP状态码 的方式,最简单的就是直接返回指定的类型实例,如下代码所示: [ApiController] [Route("[controller]")] public class WeatherForecastController : ControllerBase { [HttpGet] public IEnumerable<WeatherForecast> Get() { var rng = new Random()

  • ASP.NET Core中实现全局异常拦截的完整步骤

    前言 异常是一种运行时错误,当异常没有得到适当的处理,很可能会导致你的程序意外终止,这篇就来讨论一下如何在 ASP.Net Core MVC 中实现全局异常处理,我会用一些 样例代码 和 截图 来说明这些概念. 全局异常处理 其实在 ASP.Net Core MVC 框架中已经有了全局异常处理的机制,你可以在一个中心化的地方使用 全局异常处理中间件 来进行异常拦截,如果不用这种中心化方式的话,你就只能在 Controller 或者 Action 作用域上单独处理,这会导致异常处理代码零散在项目各

  • ASP.NET Core中如何实现重定向详解

    前言 ASP.NET Core 是一个跨平台,开源的,轻量级的,模块化的,用于构建高性能的 web 开发框架, ASP.NET Core MVC 内置了多种方式将一个 request 请求跳转到指定的url,这篇文章我们就来讨论如何去实现. 理解 RedirectActionResult ASP.NET Core MVC 中内置了几种 Redirect,比如说:RedirectResult, RedirectToActionResult, RedirectToRouteResult 和 Loca

  • ASP.NET Core对不同类型的用户进行区别限流详解

    前言 老板提出了一个新需求,从某某天起,免费用户每天只能查询100次,收费用户100W次. 这是一个限流问题,聪明的你也一定想到了如何去做:记录用户每一天的查询次数,然后根据当前用户的类型使用不同的数字做比较,超过指定的数字就返回错误. 嗯,原理就是这么简单.不过真正写起来还要考虑更多问题: 统计数据的数据结构是什么样的?字典 or 行记录? 统计数据记录到哪里?内存 or MySQL or Redis? 分布式应用怎么精确计数?分布式锁 or 队列 or 事务? 吞吐量比较大时如何扛得住?内存

  • 如何在Asp.Net Core中集成Refit

    在很多时候我们在不同的服务之间需要通过HttpClient进行及时通讯,在我们的代码中我们会创建自己的HttpClient对象然后去跨领域额进行数据的交互,但是往往由于一个项目有多个人开发所以在开发中没有人经常会因为不同的业务请求去写不同的代码,然后就会造成各种风格的HttpClient的跨域请求,最重要的是由于每个人对HttpClient的理解程度不同所以写出来的代码可能质量上会有参差不齐,即使代码能够达到要求往往也显得非常臃肿,重复高我们在正式介绍Refit这个项目之前,我们来看看我们在项目

  • ASP.NET Core 使用Cookie验证身份的示例代码

    ASP.NET Core 1.x提供了通过Cookie 中间件将用户主体序列化为一个加密的Cookie,然后在后续请求中验证Cookie并重新创建主体,并将其分配给HttpContext.User属性.如果您要提供自己的登录界面和用户数据库,可以使用作为独立功能的Cookie中间件. ASP.NET Core 2.x的一个主要变化是不再存在Cookie中间件.取而代之的是在Startup.cs文件中的Configure方法中的调用UseAuthentication方法会添加设置HttpConte

随机推荐