Commit e418ef69 authored by 潘栩锋's avatar 潘栩锋 🚴

添加 数据库按月备份。 当前使用的数据库只能保存当前月与上一个月

parent 092e1146
......@@ -5,7 +5,6 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="290" d:DesignWidth="687"
Background="#bcbcbc"
Title="Page1">
<Page.Resources>
<ResourceDictionary>
......@@ -15,7 +14,7 @@
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Page.Resources>
<Grid>
<Grid Background="{StaticResource Brushes.NoAct}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="90*" />
<ColumnDefinition Width="500*" />
......@@ -35,10 +34,10 @@
<TextBlock Margin="5" Name="textBlock1" VerticalAlignment="Bottom" Text="加载中" FontSize="24"/>
</Viewbox>
<Grid Grid.Row="1">
<Rectangle Stroke="{StaticResource Color_theme_activity}"/>
<Rectangle Stroke="{StaticResource Brushes.Activity}"/>
<Grid Margin="2" >
<Rectangle Fill="{StaticResource Color_theme_static}" x:Name="rectangle_bg_epc"/>
<Rectangle HorizontalAlignment="Left" Fill="{StaticResource Color_theme_activity}" >
<Rectangle Fill="{StaticResource Brushes.Static}" x:Name="rectangle_bg_epc"/>
<Rectangle HorizontalAlignment="Left" Fill="{StaticResource Brushes.Activity}" >
<Rectangle.Width>
<MultiBinding Converter="{StaticResource ratioconv}" Mode="OneWay">
<Binding Path="Progress" />
......
......@@ -4,7 +4,7 @@
<!--激活颜色-->
<SolidColorBrush x:Key="Brushes.Activity" Color="{StaticResource MahApps.Colors.AccentBase}"/>
<!--不活动颜色-->
<SolidColorBrush x:Key="Brushes.Static" Color="{StaticResource MahApps.Colors.Gray2}"/>
<SolidColorBrush x:Key="Brushes.Static" Color="{StaticResource MahApps.Colors.Gray1}"/>
<!--不活动颜色-->
<SolidColorBrush x:Key="Brushes.NoAct" Color="{StaticResource MahApps.Colors.Gray5}"/>
<!--背景色-->
......
......@@ -35,27 +35,6 @@
<TextBlock Style="{StaticResource Styles.Card.Title}"
Text="基本"/>
<StackPanel >
<StackPanel Orientation="Horizontal">
<StackPanel Margin="{StaticResource ControlMargin}">
<TextBlock Style="{StaticResource Styles.Text.FieldHeader.Editable}" Text="数据库容量" />
<StackPanel Orientation="Horizontal">
<TextBox Style="{StaticResource Styles.Text.FieldContent.Input.Card}" Text="{Binding DBKeepMonth}" />
<TextBlock Style="{StaticResource Styles.Text.FieldContent.Unit}" Text="月" />
</StackPanel>
</StackPanel>
<StackPanel Margin="{StaticResource ControlMargin}">
<StackPanel Orientation="Horizontal">
<TextBlock Style="{StaticResource Styles.Text.FieldHeader.Editable}" Text="数据库文件路径" />
<Button Style="{StaticResource Styles.Button.Icon}" Command="{Binding SelectDbPathCmd}" >
<iconPacks:PackIconMaterial Kind="FolderOpen" />
</Button>
</StackPanel>
<Viewbox Height="36" HorizontalAlignment="Left" >
<TextBlock Style="{StaticResource Styles.Text.FieldContent}" Text="{Binding DbPath}" />
</Viewbox>
</StackPanel>
</StackPanel>
<StackPanel Orientation="Horizontal">
<StackPanel Margin="{StaticResource ControlMargin}">
......
......@@ -164,19 +164,11 @@ namespace FLY.Thick.Base.UI
#endregion
/// <summary>
/// 数据库保存的月数
/// </summary>
public int DBKeepMonth { get; set; }
/// <summary>
/// 数据库路径
/// </summary>
public string DbPath { get; set; }
#endregion
#region Command
public RelayCommand ApplyCmd { get; }
public RelayCommand SelectDbPathCmd { get; }
#endregion
......@@ -185,7 +177,6 @@ namespace FLY.Thick.Base.UI
public PgInitParamVm()
{
ApplyCmd = new RelayCommand(Apply);
SelectDbPathCmd = new RelayCommand(SelectDbPath);
}
......@@ -215,8 +206,6 @@ namespace FLY.Thick.Base.UI
Misc.BindingOperations.SetBinding(initParamService, nameof(initParamService.DTime), this, nameof(DTime));
Misc.BindingOperations.SetBinding(initParamService, nameof(initParamService.HVelocity1), this, nameof(HVelocity1));
Misc.BindingOperations.SetBinding(initParamService, nameof(initParamService.HVelocity2), this, nameof(HVelocity2));
Misc.BindingOperations.SetBinding(initParamService, nameof(initParamService.DBKeepMonth), this, nameof(DBKeepMonth));
Misc.BindingOperations.SetBinding(initParamService, nameof(initParamService.DbDirPath), this, nameof(DbPath));
Misc.BindingOperations.SetBinding(initParamService, nameof(initParamService.PunchOffset), this, nameof(PunchOffset));
Misc.BindingOperations.SetBinding(initParamService, nameof(initParamService.HasPunch), this, nameof(HasPunch));
......@@ -255,8 +244,6 @@ namespace FLY.Thick.Base.UI
initParamService.DTime = this.DTime;
initParamService.HVelocity1 = this.HVelocity1;
initParamService.HVelocity2 = this.HVelocity2;
initParamService.DBKeepMonth = this.DBKeepMonth;
initParamService.DbDirPath = this.DbPath;
initParamService.HasPunch = this.HasPunch;
initParamService.PunchOffset = this.PunchOffset;
......@@ -272,18 +259,5 @@ namespace FLY.Thick.Base.UI
TimeSpan.FromSeconds(2));
}
private void SelectDbPath()
{
System.Windows.Forms.FolderBrowserDialog open = new System.Windows.Forms.FolderBrowserDialog();
open.SelectedPath = DbPath;
if (open.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
DbPath = open.SelectedPath;
}
}
}
}
......@@ -28,6 +28,8 @@ namespace FLY.Thick.Base.Common
public ERRNO SCAN_ERRNO_OVERTOL = new ERRNO() { Code = 12, Descrption = "扫描超规格报警" };
public ERRNO BASE_ERRNO_DB = new ERRNO() { Code = 13, Descrption = "数据库异常,重建" };
public ERRNO BASE_ERRNO_TIMEGRIDADV = new ERRNO() { Code = 14, Descrption = "AD卡版本太低,不能启动 [高级AD数据]" };
public ERRNO BASE_ERRNO_DB_BACKUP = new ERRNO() { Code = 15, Descrption = "已经连续开机1个月,数据库需要备份归档,请尽快重启服务器" };
public ERRNO SCAN_ERRNO_FATAL = new ERRNO() { Code = 20, Descrption = "扫描异常,致命错误 必须停止扫描" };
public ERRNO SYNC_ERRNO_FATAL = new ERRNO() { Code = 21, Descrption = "同步异常,致命错误 必须停止扫描" };
public ERRNO MEASURE_SYNC_ERRNO_FATAL = new ERRNO() { Code = 22, Descrption = "测量同步参数异常,致命错误 必须停止" };
......
......@@ -85,7 +85,7 @@ namespace SQLite
return null;
string del_time_str = del_time.ToStringOfSQLiteFieldType();
//获取 比 del_time 小的 最后一个ID
var ret = sqliteHelper.ExecuteScalar($"SELECT ID FROM {TableName} WHERE {TimeFieldName} < {del_time_str} ORDER BY ID DESC LIMIT 1");
if (ret != null)
{
......
......@@ -4,6 +4,7 @@ using System.Data.SQLite;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace SQLite
......@@ -225,7 +226,10 @@ namespace SQLite
}
}
/// <summary>
/// 使数据库 只储存 从现在向前 N个月的数据
/// </summary>
/// <param name="month"></param>
public void KeepDBSize(int month)
{
if (month < 1)
......@@ -258,6 +262,237 @@ namespace SQLite
sqliteHelper.QueryTran(sqls);
}
/// <summary>
/// 数据库按月备份,当前月不备份
/// </summary>
public void BackupDb()
{
BackupBbInSize(10 * 12);
}
/// <summary>
/// 数据库按月备份,当前月不备份, 只保存从现在开始向前的N个月
/// </summary>
/// <param name="month"></param>
public void BackupBbInSize(int month)
{
if (month < 12)
month = 12;
//保存当前月份除外的全部月份数据
//保存到当前数据库所在的文件夹内
//获取全部带来时间field 的表, 最早的那行时间
var firstTimes = new List<DateTime>();
foreach (IDBTable tb in DbSet)
{
if (string.IsNullOrEmpty(tb.TimeFieldName))
continue;
string sql = $"SELECT {tb.TimeFieldName} FROM {tb.TableName} ORDER BY ID LIMIT 1";
var ret = sqliteHelper.ExecuteScalar(sql);
if (ret == null)
continue;//一行数据也没有
if (!(ret is DateTime))
continue;//异常,返回的不是时间
var firstTime = (DateTime)ret;
firstTimes.Add(firstTime);
}
DateTime curr_month = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
int curr_total_month = curr_month.Year * 12 + curr_month.Month;
int limit_total_month = curr_total_month - month;
DateTime limit_month = new DateTime( limit_total_month/12, limit_total_month % 12, 1);
DateTime start_month = firstTimes.Min();
start_month = new DateTime(start_month.Year, start_month.Month, 1);
if (start_month < limit_month)
start_month = limit_month;
if (start_month >= curr_month)
{
//最早的时间,都只是本月而已。不需要备份
return;
}
DateTime i_month = start_month;
//开始逐月备份
//先检测是否已经备份了
while (true)
{
if (IsNeedToBackup(i_month))//需要备份
BackupDb(i_month);
i_month = i_month.AddMonths(1);
if (i_month >= curr_month)
{
//已经全部备份完成
break;
}
}
}
string GetBackupDbPath(DateTime month)
{
string dirPath = Path.Combine(Path.GetDirectoryName(DBPath), $"{month:yyyy-MM}");
string dbPath = Path.Combine(dirPath, Path.GetFileName(DBPath));
return dbPath;
}
void BackupDb(DateTime month)
{
string backup_dbPath = GetBackupDbPath(month);
//把整个文件复制过去,再把其它月份的数据删除
try
{
//先创建文件夹
string dirPath = Path.GetDirectoryName(backup_dbPath);
Directory.CreateDirectory(dirPath);
//再复制
File.Copy(DBPath, backup_dbPath);
}
catch {
//失败
return;
}
//删除其它月份的数据
SQLiteHelper sqliteHelper2 = new SQLiteHelper();
sqliteHelper2.ConnectionString = $"Data Source={backup_dbPath};Version=3;";
List<string> sqls = new List<string>();
DateTime next_month = month.AddMonths(1);
//枚举全部TbXXX, 带有TimeAttribute 都删除
foreach (IDBTable tb in DbSet)
{
if (string.IsNullOrEmpty(tb.TimeFieldName))
continue;
string sql = $"DELETE FROM {tb.TableName}" +
$" WHERE {tb.TimeFieldName} < '{month:yyyy-MM}-01'" +
$" OR {tb.TimeFieldName}>='{next_month:yyyy-MM}-01'";
sqls.Add(sql);
}
//把sqls里面为空的全部删除
if (sqliteHelper2.QueryTran(sqls)) {
sqliteHelper2.ExecuteNonQuery("VACUUM");
}
}
public bool IsNeedToBackup()
{
DateTime curr_month = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
DateTime pre_month = curr_month.AddMonths(-1);
return IsNeedToBackup(pre_month);
}
/// <summary>
/// 需要备份
/// </summary>
bool IsNeedToBackup(DateTime month)
{
// 步骤1, 比步骤2时间要短
//1. 检测是否有上一个月的备份文件路径
string pre_dbPath = GetBackupDbPath(month);
if (File.Exists(pre_dbPath))
{
//已经备份了
return false;
}
//没有备份
//2.检测当前的数据库,是否有上一个月的数据
bool hasData = false;
foreach (IDBTable tb in DbSet)
{
if (string.IsNullOrEmpty(tb.TimeFieldName))
continue;
//检测是否有这个月份的数据
//SELECT ID FROM Sample WHERE Time LIKE '2021-06%' LIMIT 1
string sql = $"SELECT ID FROM {tb.TableName} WHERE {tb.TimeFieldName} LIKE '{month:yyyy-MM}%' LIMIT 1";
var ret = sqliteHelper.ExecuteScalar(sql);
if (ret == null)
continue;//没有这个月的数据
//有数据
hasData = true;
break;
}
return hasData;//有数据,需要备份 ;
}
/// <summary>
/// 限制备份的数据包数量,最少1年
/// </summary>
/// <param name="yeah"></param>
public void KeepBackupSize(int month)
{
if (month < 12)
month = 12;
int curr_month = DateTime.Now.Year*12 + DateTime.Now.Month;
int del_month = curr_month - month;
//枚举文件夹 全部 yyyy-MM 格式的数据
Regex regex = new Regex(@"\A(\d\d\d\d)-(\d\d)\z");
var dirInfo = new DirectoryInfo(Path.GetDirectoryName(DBPath));
var dirInfos = dirInfo.GetDirectories();
foreach (var dinfo in dirInfos) {
var match = regex.Match(dinfo.Name);
if (match.Success) {
if (!int.TryParse(match.Groups[1].Value, out int y))
continue;
if (!int.TryParse(match.Groups[2].Value, out int m))
continue;
if (m > 12 || m < 1)
continue;//异常
if (y < 1900 || y > 2100)
continue;//异常
int total_m = y * 12 + m;
if (total_m > del_month)
continue;
//需要删除
//检查是否有数据库文件
string dbPath = GetBackupDbPath(new DateTime(y, m, 1));
try
{
File.Delete(dbPath);
}
catch {
//删除失败
continue;
}
try
{
//删除空目录,不为空,就会异常
Directory.Delete(dinfo.FullName);
}
catch {
continue;
}
}
}
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment