主頁 > .NET開發 > EFCore生產環境資料庫升級方案

EFCore生產環境資料庫升級方案

2021-08-31 15:49:55 .NET開發

這里之所以推薦使用生成SQL的方式來應用遷移,是因為將遷移生成SQL腳本后,更具靈活性,主要有以下幾點好處:

1 、我們可以根據需要來在遷移生成的SQL腳本基礎上進行刪級訓者增加腳本

2、可以直接將腳本發給資料庫管理員進行升級,

3、可以檢查遷移生成所生成的SQL腳本的正確性,避免破壞性的升級,

一、環境準備

  1. 安裝efcore cli 命令列工具:打開程式包管理控制臺,輸入:dotnet tool install --global dotnet-ef,如果已安裝請跳過此步驟,
  2. 新建一個asp.net core mvc 專案和一個類別庫專案,如下圖

二、創建DbContext

首先往類別庫專案添加EFCore 相關的Nuget包以及應用遷移的dbup-sqlserver包, Microsoft.EntityFrameworkCore.SqlServer、Microsoft.EntityFrameworkCore.Design、dbup-sqlserver,如下圖所示:

然后定義一個物體模型UserInfo和DbContext

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text;

namespace EFMigrations.Models
{
    public class UserInfo
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int UserId { get; set; }
        public string UserName { get; set; }
        public string Password { get; set; }
        public string Email { get; set; }
    }
}
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Text;

namespace EFMigrations.Models
{
    public class MyDbContext : DbContext
    {
        /// <summary>
        /// 這里一定要宣告一個接收DbContextOptions引數的建構式,否則無法正常添加遷移,
        /// </summary>
        /// <param name="options"></param>
        public MyDbContext(DbContextOptions<MyDbContext> options) : base(options)
        {
        }
        public DbSet<UserInfo> UserInfos { get; set; }
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            base.OnConfiguring(optionsBuilder);
        }
    }
}

 

三、配置Web專案

1 添加Microsoft.EntityFrameworkCore.Design  Nuget包的參考,參考后,記得重新生成下專案,

2 打開appsettings.Development.json,配置資料庫連接字串,如下所示:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "ConnectionStr": "Server=.;Database=TestDb;User Id=sa;Password=xxxx"
  }
}

3 打開Startup.cs 檔案,將DbContext注冊到服務容器中,

 

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<MyDbContext>(builder=> {
                builder.UseSqlServer(Configuration["ConnectionStrings:ConnectionStr"]);
            });
            services.AddControllersWithViews();
        }

 

三、添加遷移

先看下遷移命令的使用說明,打開程式包管理控制臺,輸入以下命令來查看遷移生成命令的使用方式:

dotnet ef migrations add --help

 

 

-s 選項:表示生成遷移時要啟動的專案,這里是EFMigrations.Web

-p 選項:指定要存放遷移檔案的專案根目錄,正常就是DbContext類所在的專案,

-o 選項:可以額外指定遷移檔案要存放的目錄,不指定該選項則默認生成到-p 選項所在專案的Migrations檔案夾下

打開程式包管理控制臺,輸入命令:dotnet ef migrations add InitDatabase -s ./EFMigrations.Web -p ./EFMigrations.Models,來生成首個遷移,這里遷移的名稱可以自定義,不一定要叫InitDatabase.成功后如下圖所示:

// <auto-generated />
using EFMigrations.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;

namespace EFMigrations.Models.Migrations
{
    [DbContext(typeof(MyDbContext))]
    partial class MyDbContextModelSnapshot : ModelSnapshot
    {
        protected override void BuildModel(ModelBuilder modelBuilder)
        {
#pragma warning disable 612, 618
            modelBuilder
                .HasAnnotation("ProductVersion", "3.1.18")
                .HasAnnotation("Relational:MaxIdentifierLength", 128)
                .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);

            modelBuilder.Entity("EFMigrations.Models.UserInfo", b =>
                {
                    b.Property<int>("UserId")
                        .ValueGeneratedOnAdd()
                        .HasColumnType("int")
                        .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);

                    b.Property<string>("Email")
                        .HasColumnType("nvarchar(max)");

                    b.Property<string>("Password")
                        .HasColumnType("nvarchar(max)");

                    b.Property<string>("UserName")
                        .HasColumnType("nvarchar(max)");

                    b.HasKey("UserId");

                    b.ToTable("UserInfos");
                });
#pragma warning restore 612, 618
        }
    }
}

可以看到MyDbContextModelSnapshot.cs 檔案中的內容此時也記錄了InitDatabase 遷移中的更改,即EF每次生成遷移時是將遷移快照檔案(這里是:MyDbContextmodelSnapshot.cs)中的更改和現有模型進行比較來決定新的遷移中要包含哪些更改的,

 

四、遷移轉換成SQL腳本

先來看下將ef 遷移轉換成資料庫腳本的命令說明,打開程式包管理控制臺,輸入以下命令來查看EF遷移轉SQL腳本命令的用法:

dotnet ef migrations script --help

FROM 引數:表示從哪個遷移開始生成SQL腳本,如果是從第一個遷移開始生成,那么這個引數傳0,否則第一個遷移無法生成SQL腳本,

TO 引數:表示SQL腳本生成截止到哪一個遷移,在這個遷移后面添加的遷移將不會生成SQL腳本,

-s 選項:指定生成SQL腳本時的啟動專案的csproj檔案的路徑,可以是一個相對于當前目錄的相對路徑(程式包管理控制臺打開時默認當前目錄是在.sln檔案所在目錄),啟動專案指的是包含Main函式的可執行的專案,這里就是EFMigrations.Web

-p 選項:指定遷移所在的專案,一般該路徑指定為包含DbContext類的專案的根目錄,和 -s 一樣,也是使用相對于當前目錄的相對路徑來指定,可以使用

dir 命令 來查看當前所在目錄,

-o 選項:用于指定將SQL腳本生成到那個路徑下,可以是一個相對目錄,

 

輸入 cd ./EFMigrations.Models 進入到包含DbContext類的專案根目錄下,這樣我們就可以不用特意指定DbContext 所在的專案路徑,

輸入 dotnet ef migrations script 0 20210826142318_InitDatabase -s ../EFMigrations.Web -o ./SqlScripts/InitDatabase.sql

上面這個命令表示將20210826142318_InitDatabase 這個遷移生成的SQL存放到EFMigrations.Models/SqlScripts 目錄下,

成功后,可以看到如下圖所示:

注意:洗掉遷移盡量使用dotnet ef migrations remove 來洗掉,盡量不要手動洗掉遷移檔案,因為如果手動洗掉遷移檔案,必須手動將遷移快照(MyDbContextModelSnapShot.cs)檔案里關于這個遷移的變更一起洗掉,否則無法再次生成這個遷移,

 

需要將.sql 腳本設定為內嵌資源,滑鼠右擊.sql腳本,選擇屬性->生成操作->嵌入的資源,按照如下設定:

五、首個遷移應用

1、在EFMigrations.Models 專案下添加 ApplicationBuilderExtensions類

using DbUp;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;

namespace EFMigrations.Models
{
    public static class ApplicationBuilderExtensions
    {
        public static void DbMigrate(this IApplicationBuilder builder, IConfiguration configuration,ILogger logger)
        {
            string connectionString = configuration["ConnectionStrings:ConnectionStr"];
            //如果資料庫還不存在,則創建
            EnsureDatabase.For.SqlDatabase(connectionString);

            //這里將會去找當前程式集中所包含的所有.sql 腳本,并且找出未被升級的sql腳本進行升級,
            var upgrader = DeployChanges.To
            .SqlDatabase(connectionString)
            .WithScriptsEmbeddedInAssembly(Assembly.GetExecutingAssembly())
            .LogToConsole()
            .Build();

            var result = upgrader.PerformUpgrade();

            if (!result.Successful)
            {
                logger.LogInformation(result.Error, "資料庫升級失敗");
            }
        }
    }
}

 

2、打開EFMigrations.Web 下的Startup.cs檔案,修改Configure方法如下:

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env,ILogger<Startup> logger)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }
            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });

            //這里開始應用資料庫遷移
            app.DbMigrate(Configuration,logger);
        }

成功后,可看到已經創建了資料庫TestDb 和 表 UserInfo

 

這里SchemaVersions 是db-sqlserver 創建的用于記錄那些SQL腳本已被應用的表,

六、變更遷移應用

上面僅僅只是創建了一個遷移,假設我們這個時候又往UserInfo物體新增了幾個欄位,那么我們要這個模型的變更同步到正式環境的資料庫改怎么做呢?

1、 生成遷移

 dotnet ef migrations add UserInfo_AddColumns -p ./EFMigrations.Models/EFMigrations.Models.csproj -s ./EFMigrations.Web/

2、遷移轉換成SQL腳本,并嵌入到程式集,然后將程式集編譯發布到正式環境

cd ./EFMigrations.Models

dotnet ef migrations script 20210826142318_InitDatabase 20210830142733_UserInfo_AddColumns -o ./SqlScripts/UserInfo_AddColumns.sql -s ../EFMigrations.Web/ 

這里-o 后面一定要指定sql檔案名,如果只指定目錄如:-o ./SqlScripts/ 則會提示路徑找不到,

另外需要注意的是:FROM 引數指定的遷移(20210826142318_InitDatabase )是會被排除在外的,不會生成相應的SQL腳本,

生成SQL腳本后記得將該腳本的生成操作設定為嵌入資源,

3、重啟網站即可,

可以看到,重啟網站后,欄位創建成功了,

dbup 官方檔案地址:https://dbup.readthedocs.io/en/latest/#getting-started

 

337901356

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/295812.html

標籤:.NET技术

上一篇:c# 異步呼叫 利用委托異步呼叫

下一篇:通過模板匯出word

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more