需求
- 将A服务器的sql server数据库item_mst表的数据同步到MySQL数据库Part表
- 监控Item_mst表中item,description,overview 的更改并同步到MySQL数据库
针对需求一,基本就是执行一次,单独写了个winform用来做这事
针对需求二,写了个Windows service app
Nuget安装
Dapper就是个orm
Serilog用来记log
SQLTableDependency用来检测表的改动,文档地址:https://github.com/christiandelbianco/monitor-table-change-with-sqltabledependency
使用这个别忘了执行 alter database [<dbname>] set enable_broker with rollback immediate;
- 创建service
- 添加安装程序
- 如何安装service
Create a Windows service app
How to: Add Installers to Your Service Application
https://docs.microsoft.com/zh-cn/dotnet/framework/windows-services/how-to-add-installers-to-your-service-application
How to: Install and uninstall Windows services
https://docs.microsoft.com/en-us/dotnet/framework/windows-services/how-to-install-and-uninstall-services
源码
目录结构
Models文件夹里的ItemMst.cs文件
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SyncItemMstAllService.Models
{
/// <summary>
/// table name: item_mst
/// note: We do not need to specify all table columns but just the ones we are interested:
/// </summary>
public class ItemMst
{
// internalNumber
public string Item { get; set; }
// name
public string Description { get; set; }
// description
public string Overview { get; set; }
}
}
App.config
<appSettings>
<add key="logFilesPath" value="C:\QMSCSyncData\logs\"/>
<add key="webApiBaseAddress" value="http://localhost:5000/"/>
</appSettings>
<connectionStrings>
<add name="JMP_APP_SqlServerConnStr" connectionString="data source=192.168.1.202\test;initial catalog=JMP_APP;User Id=sa;Password=pwd;"/>
<add name="QMS_MySqlServerConnStr" connectionString="server=localhost;Port=3306;Database=qms_test;UID=root;PWD=pwd;Allow User Variables=True" /> </connectionStrings>
Allow User Variables=True"这个东西我不知道干啥的,但我知道没他就会出现错误- -
不加会出现这样的情况
QMSSyncTiemMstService.cs
using System;
using System.Configuration;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.ServiceProcess;
using System.Threading.Tasks;
using Dapper;
using SyncItemMstAllService.Models;
using MySql.Data.MySqlClient;
using Serilog;
using TableDependency.SqlClient;
using TableDependency.SqlClient.Base.Enums;
using TableDependency.SqlClient.Base.EventArgs;
using System.Collections.Generic;
namespace QMSCSyncService
{
public partial class QMSSyncItemMstService : ServiceBase
{
private SqlTableDependency<ItemMst> _itemMstAllSyncDependency;
private readonly string _jmp_app_ConnectionString;
private readonly string _qms_mysql_ConnectionString;
private readonly string _logFilesPath;
private readonly string version = "1.0.20190730";
public QMSSyncItemMstService()
{
InitializeComponent();
_logFilesPath = ConfigurationManager.AppSettings["logFilesPath"];
_jmp_app_ConnectionString = ConfigurationManager.ConnectionStrings["JMP_APP_SqlServerConnStr"].ConnectionString;
_qms_mysql_ConnectionString = ConfigurationManager.ConnectionStrings["QMS_MySqlServerConnStr"].ConnectionString;
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.File($"{_logFilesPath}serviceLog.txt", rollingInterval: RollingInterval.Day)
.CreateLogger();
}
protected override void OnStart(string[] args)
{
initItemMstAllSyncDependency();
Log.Information($"QMSSyncService Started.Version{version}");
}
protected override void OnStop()
{
Log.Information("QMSSyncService Stopped.");
try
{
if (_itemMstAllSyncDependency != null)
{
_itemMstAllSyncDependency.Stop();
_itemMstAllSyncDependency.Dispose();
}
}
catch (Exception ex)
{
Log.Error($"Error occur when stopping service, {ex.Message} {ex.Source}");
}
}
private void initItemMstAllSyncDependency()
{
Log.Information($"run initItemMstAllSyncDependency");
try
{
if (_itemMstAllSyncDependency != null)
{
_itemMstAllSyncDependency.Stop();
_itemMstAllSyncDependency.Dispose();
}
_itemMstAllSyncDependency = new SqlTableDependency<ItemMst>(_jmp_app_ConnectionString, "item_mst");
_itemMstAllSyncDependency.OnChanged += ItemMstAllSyncDependency_OnChanged;
_itemMstAllSyncDependency.OnError += ItemMstAllSyncDependency_OnError;
_itemMstAllSyncDependency.Start();
}
catch (Exception ex)
{
Log.Error($"Init SqlTableDependency for ItemMstSyncs failed. {ex.Message} {ex.Source}");
if (_itemMstAllSyncDependency != null)
{
_itemMstAllSyncDependency.Stop();
_itemMstAllSyncDependency.Dispose();
}
}
private void ItemMstAllSyncDependency_OnChanged(object sender, RecordChangedEventArgs<ItemMst> e)
{
if (e.ChangeType != ChangeType.None)
{
switch (e.ChangeType)
{
case ChangeType.Insert:
case ChangeType.Update:
saveItemMst(e.Entity.Item, e.Entity.Description, e.Entity.Overview);
break;
}
}
}
private void saveItemMst(string item, string name, string description)
{
string UUID = Guid.NewGuid().ToString("D");
DateTime dt = DateTime.Now;
bool hasExisted = isExisted(item);
if (name == null)
{
name = item;
}
string insertSql = $@"INSERT INTO `part` (
`ParentPartId`,
`PublisherId`,
`UUID`,
`Type`,
`InternalNumber`,
`SupplierNumber`,
`Name`,
`Description`,
`Rev`,
`RevType`,
`Level`,
`Category`,
`Status`,
`CreatedAt`,
`CreatedBy`,
`IsDeleted`
)
VALUES
(
0,
149,
@UUID,
1,
@item,
NULL,
@name,
@description,
'A',
1,
1,
'',
1,
'{dt}',
701,
0
);";
string updateSql = $@"UPDATE `part`
SET
`Name` = @name,
`Description` = @description,
`UpdatedAt` = '{dt}',
`UpdatedBy` = '701'
WHERE InternalNumber = @item";
try
{
using (MySqlConnection qmsDBConnection = new MySqlConnection(_qms_mysql_ConnectionString))
{
qmsDBConnection.Open();
using (MySqlCommand cmd = qmsDBConnection.CreateCommand())
{
try
{
cmd.CommandText = hasExisted ? updateSql : insertSql;
cmd.Parameters.Add(new MySqlParameter("@UUID", UUID));
cmd.Parameters.Add(new MySqlParameter("@name", name));
cmd.Parameters.Add(new MySqlParameter("@description", description));
cmd.Parameters.Add(new MySqlParameter("@item", item));
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
Log.Error($"Sync from saveItemMst have error occur, {ex.Message} {ex.Source} { ex.StackTrace }");
}
}
}
}
catch (Exception ex)
{
Log.Error($"Sync from saveItemMst have error occur, {ex.Message} {ex.Source} { ex.StackTrace }");
}
}
private bool isExisted(string item)
{
string sSql = @"SELECT * FROM Part P WHERE P.PublisherId=149 AND P.InternalNumber = @item AND P.IsDeleted=0";
try
{
using (MySqlConnection qmsDBConnection = new MySqlConnection(_qms_mysql_ConnectionString))
{
qmsDBConnection.Open();
using (MySqlCommand cmd = new MySqlCommand(sSql, qmsDBConnection))
{
try
{
cmd.Parameters.Add(new MySqlParameter("@item", item));
object result = cmd.ExecuteScalar();
if (result != null)
{
return true;
}
return false;
}
catch (Exception ex)
{
Log.Error($"IsExisted have error occur, {ex.Message} {ex.Source} { ex.StackTrace }");
return false;
}
}
}
}
catch (Exception ex)
{
Log.Error($"IsExisted have error occur, {ex.Message} {ex.Source} { ex.StackTrace }");
return false;
}
}
}
private void ItemMstAllSyncDependency_OnError(object sender, TableDependency.SqlClient.Base.EventArgs.ErrorEventArgs e)
{
string innerException = e.Error.InnerException != null ? e.Error.InnerException.Message + e.Error.InnerException.Source : "";
Log.Error($"ItemMstAllSyncDependency have error occur, {e.Error.Message} {e.Error.Source} { innerException }");
try
{
this.OnStop();
this.OnStart(null);
}
catch (Exception ex)
{
Log.Debug("Restart failed " + ex.Message + ex.Source);
}
}
}
}
标签:string,C#,数据库,System,item,ex,MySQL,using,itemMstAllSyncDependency From: https://blog.51cto.com/u_15976398/6166425