欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

c#使用FreeSql生產(chǎn)環(huán)境時自動升級備份數(shù)據(jù)庫

 更新時間:2021年06月22日 08:30:47   作者:一級碼農(nóng)VIP  
使用FreeSql,包含所有的ORM數(shù)據(jù)庫,都會存在這樣的問題。在codefirst模式下,根據(jù)代碼自動更新數(shù)據(jù)庫,都建議不要在生產(chǎn)環(huán)境使用。因為容易丟失數(shù)據(jù),本文提供一種自動更新數(shù)據(jù)庫的解決的思路:在判斷需要升級時,才自動升級,同時升級前先備份數(shù)據(jù)庫

項目場景:

使用FreeSql,包含所有的ORM數(shù)據(jù)庫,都會存在這樣的問題。在codefirst模式下,根據(jù)代碼自動更新數(shù)據(jù)庫,都建議不要在生產(chǎn)環(huán)境使用。為什么呢?
其實不建議使用,主要是根據(jù)代碼自動生成數(shù)據(jù)時,極有可能會造成數(shù)據(jù)的丟失,比如修改字段類型,自動更新的結(jié)果可能并不是自己想的。
但是有一些使用場景是需要在生產(chǎn)環(huán)境自動升級的,比如
我們有一個CS客戶端的產(chǎn)品,客戶本地離線使用,客戶本地部署,數(shù)據(jù)庫也是本地數(shù)據(jù)庫,版本從1000,迭代到了1100,中間發(fā)布了100個版本。這中間可能有多次數(shù)據(jù)庫更改。我們的客戶也可能遍布全國各地,版本也都不相同。客戶如果沒有新的需求,可能會一直使用當(dāng)前舊版本,只有在有新的需求,或者想使用新的功能時,才會升級版本。所以升級的時間也是不確定的,升級要求客戶安裝新版軟件,運行后自動升級。
那就真的不能在生產(chǎn)環(huán)境使用呢?

解決方案:

概要描述:

解決的思路其實就是自動升級,但是在判斷需要升級時,才自動升級,同時升級前先備份數(shù)據(jù)庫。

具體流程
程序內(nèi)每次有數(shù)據(jù)庫變更,發(fā)布版本時,修改程序內(nèi)對應(yīng)版本。比如最開始是1000,最新是1100
在數(shù)據(jù)庫增加SysConfig表,字段包含DbVer表示當(dāng)前數(shù)據(jù)庫版本號
在數(shù)據(jù)庫增加DbLog表,記錄數(shù)據(jù)庫升級日志,此項可選
在首次安裝時,檢查數(shù)據(jù)庫文件不存在,表示首次安裝,首次安裝時創(chuàng)建SysConfig表和DbLog表,同時更新SysConfig表DbVer為程序中記錄版本號。增加DbLog表日志
以后再次運行時,先獲取SysConfig表DbVer,判斷與程序中是否一致,
如果數(shù)據(jù)庫比程序中大,說明運行低版本的程序,根據(jù)情況可以禁止運行。也可以不同步數(shù)據(jù)庫,繼續(xù)運行,根據(jù)實際情況決定。如果對程序和數(shù)據(jù)庫一致性要求比較高,可以禁止運行。
如果數(shù)據(jù)庫比程序小,說明數(shù)據(jù)庫需要升級,此時先備份現(xiàn)有數(shù)據(jù)庫,然后執(zhí)行同步數(shù)據(jù)庫。

詳細(xì)說明:

直接上代碼,比啥都清楚

program.cs文件代碼

using Bonn.Helper;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using FreeSql.DataAnnotations;
using WindowsClient.Model;
using System.Reflection;

namespace WindowsClient
{
    static class Program
    {
        /// <summary>
        /// 客戶數(shù)據(jù)庫路徑
        /// </summary>
        private static string CustDbPath = Application.StartupPath + $"\\數(shù)據(jù)庫\\cust.db";

        /// <summary>
        /// 數(shù)據(jù)庫ORM
        /// </summary>
        public static IFreeSql fsql;

        /// <summary>
        /// 服務(wù)器數(shù)據(jù)庫版本
        /// </summary>
        private static int ServerDbVer = 1000;


        /// <summary>
        /// 應(yīng)用程序的主入口點。
        /// </summary>
        [STAThread]
        static void Main()
        {
            try
            {

                //數(shù)據(jù)庫是否存在,用于插入初始數(shù)據(jù),必須在freesql實例化前判斷,因為實例化時會自動創(chuàng)建數(shù)據(jù)庫
                var custDbPathExists = File.Exists(CustDbPath);

                //deebug自動同步實體結(jié)構(gòu)到數(shù)據(jù)庫,release手動同步
                bool syncDbStructure = false;
#if DEBUG
                syncDbStructure = true;
#endif

                fsql = new FreeSql.FreeSqlBuilder()
                    .UseConnectionString(FreeSql.DataType.Sqlite, $@"Data Source={CustDbPath}; Pooling=true;Min Pool Size=1")
                    .UseAutoSyncStructure(syncDbStructure) //deebug自動同步實體結(jié)構(gòu)到數(shù)據(jù)庫,release手動同步
                    .UseMonitorCommand(cmd => Console.WriteLine($"線程:{cmd.CommandText}\r\n"))
                    .Build(); //請務(wù)必定義成 Singleton 單例模式

                if(syncDbStructure)
                {
                    //主要用于開發(fā)模式下,讓數(shù)據(jù)庫修改快速生效,不加此句時,只有在用到表時才會同步
                    fsql.CodeFirst.SyncStructure(GetTypesByTableAttribute());
                }

                if (custDbPathExists == false)
                {
                    //數(shù)據(jù)庫文件不存在,表示是首次安裝
                    fsql.CodeFirst.SyncStructure(GetTypesByTableAttribute());
                    var sysConfig = new SysConfig();
                    sysConfig.DbVer = ServerDbVer;
                    var dbResult = fsql.Insert(sysConfig).ExecuteAffrows();
                    if (dbResult <= 0)
                        throw new Exception("初始數(shù)據(jù)庫失敗。");

                    var row = new DbLog();
                    row.DbVer = ServerDbVer;
                    fsql.Insert(row).ExecuteAffrows();
                }
                int localDbVer = fsql.Select<SysConfig>().First().DbVer;
                if (localDbVer != ServerDbVer)
                {
                    //數(shù)據(jù)庫版本不一樣,需要升級
                    //備份數(shù)據(jù)庫
                    File.Copy(CustDbPath, Application.StartupPath + $"\\數(shù)據(jù)庫\\cust{DateTime.Now:yyyyMMddHHmmss}.db");
                    //升級數(shù)據(jù)庫
                    fsql.CodeFirst.SyncStructure(GetTypesByTableAttribute());
                    var row = new DbLog();
                    row.DbVer = ServerDbVer;
                    fsql.Insert(row).ExecuteAffrows();
                }

                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new FrmMain());
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString(), "出錯啦", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        public static Type[] GetTypesByTableAttribute()
        {
            List<Type> tableAssembies = new List<Type>();
            foreach (Type type in Assembly.GetAssembly(typeof(IEntity)).GetExportedTypes())
            {
                foreach (Attribute attribute in type.GetCustomAttributes())
                {
                    if (attribute is TableAttribute tableAttribute)
                    {
                        if (tableAttribute.DisableSyncStructure == false)
                        {
                            tableAssembies.Add(type);
                        }
                    }
                }
            };
            return tableAssembies.ToArray();
        }
    }
}

SysConfig.cs

using FreeSql.DataAnnotations;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WindowsClient.Model
{
    /// <summary>
    /// 
    /// </summary>
    [Table(Name = "sys_config")]
    public class SysConfig : IEntity
    {
        /// <summary>
        /// 主鍵
        /// </summary>
        [Column(Name = "id", IsIdentity = true, IsPrimary = true)]
        public int Id { get; set; }

        /// <summary>
        /// 主鍵
        /// </summary>
        [Column(Name = "dbVer")]
        public int DbVer { get; set; }

        /// <summary>
        /// 創(chuàng)建時間
        /// </summary>
        [Column(ServerTime = DateTimeKind.Local, CanUpdate = false)]
        public DateTime CreateTime { get; set; }

        /// <summary>
        /// 修改時間
        /// </summary>
        [Column(ServerTime = DateTimeKind.Local, CanUpdate = true)]
        public DateTime UpdateTime { get; set; }

    }
}

DbLog.cs

using FreeSql.DataAnnotations;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WindowsClient.Model
{
    /// <summary>
    /// 
    /// </summary>
    [Table(Name = "db_log")]
    public class DbLog : IEntity
    {
        /// <summary>
        /// 主鍵
        /// </summary>
        [Column(Name = "id", IsIdentity = true, IsPrimary = true)]
        public int Id { get; set; }

        /// <summary>
        /// 主鍵
        /// </summary>
        [Column(Name = "dbVer")]
        public int DbVer { get; set; }

        /// <summary>
        /// 創(chuàng)建時間
        /// </summary>
        [Column(ServerTime = DateTimeKind.Local, CanUpdate = false)]
        public DateTime CreateTime { get; set; }

        /// <summary>
        /// 修改時間
        /// </summary>
        [Column(ServerTime = DateTimeKind.Local, CanUpdate = true)]
        public DateTime UpdateTime { get; set; }
    }
}

總結(jié):

以前是手寫的SQL語句,現(xiàn)在用FreeSql確實方便多了。

以上就是c#使用FreeSql生產(chǎn)環(huán)境自動升級備份數(shù)據(jù)庫的詳細(xì)內(nèi)容,更多關(guān)于c# 用FreeSql自動升級備份數(shù)據(jù)庫的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 基于C#實現(xiàn)的多邊形沖突檢測實例

    基于C#實現(xiàn)的多邊形沖突檢測實例

    這篇文章主要給大家介紹了基于C#實現(xiàn)的多邊形沖突檢測的相關(guān)資料,文中介紹的方法并未使用第三方類庫,可以完美解決這個問題,需要的朋友可以參考下
    2021-07-07
  • unity實現(xiàn)多點觸控代碼

    unity實現(xiàn)多點觸控代碼

    這篇文章主要介紹了unity實現(xiàn)多點觸控代碼,我最近在學(xué)習(xí)Unity游戲引擎。先從Unity平面開始,本章介紹Unity 平面上的多點觸摸。有需要的小伙伴參考下。
    2015-03-03
  • c# Rank屬性與GetUpperBound方法的深入分析

    c# Rank屬性與GetUpperBound方法的深入分析

    本篇文章是對c#中的Rank屬性與GetUpperBound方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-06-06
  • vs2019安裝和使用詳細(xì)圖文教程

    vs2019安裝和使用詳細(xì)圖文教程

    這篇文章主要介紹了vs2019安裝和使用詳細(xì)圖文教程,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-03-03
  • Unity 實現(xiàn)給物體動態(tài)添加事件

    Unity 實現(xiàn)給物體動態(tài)添加事件

    這篇文章主要介紹了Unity 實現(xiàn)給物體動態(tài)添加事件的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • C#日期格式字符串的相互轉(zhuǎn)換操作實例分析

    C#日期格式字符串的相互轉(zhuǎn)換操作實例分析

    這篇文章主要介紹了C#日期格式字符串的相互轉(zhuǎn)換操作,結(jié)合實例形式分析了C#日期格式字符串的相互轉(zhuǎn)換操作函數(shù)與相關(guān)使用技巧,需要的朋友可以參考下
    2019-08-08
  • Unity接入百度AI實現(xiàn)果蔬識別

    Unity接入百度AI實現(xiàn)果蔬識別

    本文將介紹如何利用Unity接入百度AI從而實現(xiàn)果蔬識別,可以做到識別近千種水果和蔬菜的名稱,可自定義返回識別結(jié)果數(shù)。感興趣的小伙伴可以了解一下
    2022-02-02
  • 深入理解C#的數(shù)組

    深入理解C#的數(shù)組

    本篇文章主要介紹了C#的數(shù)組,數(shù)組是一種數(shù)據(jù)結(jié)構(gòu),詳細(xì)的介紹了數(shù)組的聲明和訪問等,有興趣的可以了解一下。
    2016-11-11
  • 快速了解如何在.NETCORE中使用Generic-Host建立主機(jī)

    快速了解如何在.NETCORE中使用Generic-Host建立主機(jī)

    這篇文章主要介紹了如何在.NETCORE中使用Generic-Host建立主機(jī),文中代碼非常詳細(xì),可供大家參考,感興趣的朋友不妨閱讀完
    2020-05-05
  • 詳解C#切換窗口

    詳解C#切換窗口

    最近項目不多忙,于是抽點時間鞏固下切換窗口問題,感興趣的朋友跟著小編一起學(xué)習(xí)吧
    2016-04-04

最新評論