首页 > 数据库 >FreeSql生产环境自动升级数据库解决方案

FreeSql生产环境自动升级数据库解决方案

时间:2023-08-16 10:23:23浏览次数:37  
标签:FreeSql 数据库 System 升级 解决方案 using public

https://www.yii666.com/blog/24613.html

 

项目场景:

使用FreeSql,包含所有的ORM数据库,都会存在这样的问题。在codefirst模式下,根据代码自动更新数据库,都建议不要在生产环境使用。为什么呢?
其实不建议使用,主要是根据代码自动生成数据时,极有可能会造成数据的丢失,比如修改字段类型,自动更新的结果可能并不是自己想的。
但是有一些使用场景是需要在生产环境自动升级的,比如
我们有一个CS客户端的产品,客户本地离线使用,客户本地部署,数据库也是本地数据库,版本从1000,迭代到了1100,中间发布了100个版本。这中间可能有多次数据库更改。我们的客户也可能遍布全国各地,版本也都不相同。客户如果没有新的需求,可能会一直使用当前旧版本,只有在有新的需求,或者想使用新的功能时,才会升级版本。所以升级的时间也是不确定的,升级要求客户安装新版软件,运行后自动升级。
那就真的不能在生产环境使用呢?文章来源地址:https://www.yii666.com/blog/24613.html

解决方案:

概要描述:

解决的思路其实就是自动升级,但是在判断需要升级时,才自动升级,同时升级前先备份数据库。网址:yii666.com<

具体流程
程序内每次有数据库变更,发布版本时,修改程序内对应版本。比如最开始是1000,最新是1100
在数据库增加SysConfig表,字段包含DbVer表示当前数据库版本号
在数据库增加DbLog表,记录数据库升级日志,此项可选
在首次安装时,检查数据库文件不存在,表示首次安装,首次安装时创建SysConfig表和DbLog表,同时更新SysConfig表DbVer为程序中记录版本号。增加DbLog表日志
以后再次运行时,先获取SysConfig表DbVer,判断与程序中是否一致,
如果数据库比程序中大,说明运行低版本的程序,根据情况可以禁止运行。也可以不同步数据库,继续运行,根据实际情况决定。如果对程序和数据库一致性要求比较高,可以禁止运行。
如果数据库比程序小,说明数据库需要升级,此时先备份现有数据库,然后执行同步数据库。

详细说明:

直接上代码,比啥都清楚文章地址https://www.yii666.com/blog/24613.html

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>
        /// 客户数据库路径
        /// </summary>
        private static string CustDbPath = Application.StartupPath + $"\\数据库\\cust.db";

        /// <summary>
        /// 数据库ORM
        /// </summary>
        public static IFreeSql fsql;

        /// <summary>
        /// 服务器数据库版本
        /// </summary>
        private static int ServerDbVer = 1000;


        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            try
            {

                //数据库是否存在,用于插入初始数据,必须在freesql实例化前判断,因为实例化时会自动创建数据库
                var custDbPathExists = File.Exists(CustDbPath);

                //deebug自动同步实体结构到数据库,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自动同步实体结构到数据库,release手动同步
                    .UseMonitorCommand(cmd => Console.WriteLine($"线程:{cmd.CommandText}\r\n"))
                    .Build(); //请务必定义成 Singleton 单例模式

                if(syncDbStructure)
                {
                    //主要用于开发模式下,让数据库修改快速生效,不加此句时,只有在用到表时才会同步
                    fsql.CodeFirst.SyncStructure(GetTypesByTableAttribute());
                }

                if (custDbPathExists == false)
                {
                    //数据库文件不存在,表示是首次安装
                    fsql.CodeFirst.SyncStructure(GetTypesByTableAttribute());
                    var sysConfig = new SysConfig();
                    sysConfig.DbVer = ServerDbVer;
                    var dbResult = fsql.Insert(sysConfig).ExecuteAffrows();
                    if (dbResult <= 0)
                        throw new Exception("初始数据库失败。");

                    var row = new DbLog();
                    row.DbVer = ServerDbVer;
                    fsql.Insert(row).ExecuteAffrows();
                }
                int localDbVer = fsql.Select<SysConfig>().First().DbVer;
                if (localDbVer != ServerDbVer)
                {
                    //数据库版本不一样,需要升级
                    //备份数据库
                    File.Copy(CustDbPath, Application.StartupPath + $"\\数据库\\cust{DateTime.Now:yyyyMMddHHmmss}.db");
                    //升级数据库
                    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文章来源地址https://www.yii666.com/blog/24613.html网址:yii666.com

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>
        /// 创建时间
        /// </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>
        /// 创建时间
        /// </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; }
    }
}

总结:

以前是手写的SQL语句,现在用FreeSql确实方便多了。感觉FreeSql。
以上方案有需要改进的,或者好的建议,希望大家评论留言。

标签:FreeSql,数据库,System,升级,解决方案,using,public
From: https://www.cnblogs.com/chinasoft/p/17633278.html

相关文章

  • log4j 配置中数据库jdbc配置: sqlonly,sqltiming,audit,resultset,connection 区别
    log4j用以下几个可以配置的日志种类:jdbc.sqlonly:仅记录SQLjdbc.sqltiming:记录SQL以及耗时信息jdbc.audit:记录除了ResultSet之外的所有JDBC调用信息,会产生大量的记录,有利于调试跟踪具体的JDBC问题jdbc.resultset:会产生更多的记录信息,因为记录了ResultSet的信......
  • 【数据库原理 | MySQL】一文打通 DDL语句
    ......
  • c# 利用数据库将程序加密隐藏?
    下面将介绍如何通过LiteDB将自己的程序进行加密,首先介绍一下LiteDB。LiteDBLiteDB是一个轻量级的嵌入式数据库,它是用C#编写的,适用于.NET平台。它的设计目标是提供一个简单易用的数据库解决方案,可以在各种应用程序中使用。LiteDB使用单个文件作为数据库存储,这个文件可以在磁盘......
  • 网页设计与网站建设连接数据库
    网页设计与网站建设连接数据库是实现动态网站的重要环节。通过连接数据库,网站可以实现用户数据的存储和读取、动态内容的生成和更新、用户交互的实现等功能。本文将介绍网页设计与网站建设连接数据库的基本步骤和要点。首先,选择合适的数据库管理系统。常见的数据库管理系统包括MyS......
  • 数据库相关
    事务:概念事务是一个不可分割的数据库操作序列,也是数据库并发控制的基本单位,其执行的结果必须使数据库从一种一致性状态到另一种一致性状态。事务是逻辑上的一组操作,要么都执行,要么都不执行。MySQL默认就是自动事务管理(自动开启事务,自动提交事务),一条sql语句就是一个事务事......
  • 手把手教你学专利检索---欧洲专利局检索数据库
    原文链接:https://zhuanlan.zhihu.com/p/549997689欧洲专利局官方网站 http://worldwide.espacenet.com/欧洲专利局(EPO)的Espacenet专利检索数据库文献覆盖面广,可以免费检索全世界100多的国家的公开专利申请,目前专利文献收录量超过1.1亿篇。首页如图1。图1其中,“Classifacati......
  • 由mysql rewrite插件带来的8.0升级问题及解决方案
    一、问题发生在客户现场遇到一个语句,走mysql的执行计划,总是不能达到预期的join顺序,需手动执行straightjoin。为了让sql能够自动转换,想到了5.7开始支持的rewriterplugin,于是在测试环境测试了一把(结果发现只能做一些简单的查询重写,稍微复杂的多表关联,总是匹配不成功,这个按下不表,......
  • 国标GB28181视频平台EasyGBS国标平台设备播放断流现象的问题解决方案
    安防视频监控EasyGBS平台基于国标GB28181协议,支持多路设备接入,并对多平台、多终端分发出RTSP、RTMP、FLV、HLS、WebRTC等多种格式的视频流。平台可为大数据等综合性监管平台提供极强的视频能力,已经在大量的项目中落地应用,如明厨亮灶、平安乡村、雪亮工程等。有用户反馈,在安防视频监......
  • vue前端项目中遇到的问题以及解决方案-不定时更新
    vue-cli创建vue项目中全局使用mixin首先需要安装插件npminstallstyle-resources-loadervue-cli-plugin-style-resources-loader--save-dev修改vue.config.js文件pluginOptions:{'style-resources-loader':{preProcessor:'scss',patterns:[//......
  • 工业物联网解决方案:粮机设备远程运维管理平台
    随着数字化转型技术的发展与进步,远程运维管理已经成为各行各业不可或缺的一部分。特别是在粮食加工行业,粮机设备的运维管理对于企业的生产效率和成本控制具有至关重要的作用。为了更好地实现粮机设备的远程运维管理,数之能提供专业高效的工业物联网解决方案。 粮机设备远程运维管理......