**
摘要
**
为帮助大家更为详细的了解RabbitMQ,本文会将配置以及消息发送接收的代码一并写出如下:
消息发送:
using GD.HTSupervisionModel.ApiModel;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using OracleToMySQL.Common;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
namespace OracleToMySQL.OracleToMySqlBLL
{
public class GetOracleTableServices
{
IModel channel;
IConnection Connection;
string DirectoryPath = "../PageParams";
MsgCenter msgCenter = new MsgCenter();
public List<string> TableList = new List<string>();
public IFreeSql dbContextO = StaticVariable.DBContext[StaticVariable.Oracle];
public IFreeSql dbContextM = StaticVariable.DBContext[StaticVariable.MySql];
ConnectionFactory Factory = new ConnectionFactory()
{
HostName = "localhost",//主机名,Rabbit会拿这个IP生成一个endpoint,这个很熟悉吧,就是socket绑定的那个终结点。
UserName = "guest",//默认用户名,用户可以在服务端自定义创建,有相关命令行
Password = "guest"//默认密码
};
/// <summary>
/// 入口
/// </summary>
public GetOracleTableServices()
{
ServiceInit();
Console.ReadKey();
}
/// <summary>
/// 初始化
/// </summary>
private void ServiceInit()
{
var fileNames = GetFilesName(new DirectoryInfo(Readjson("filePath"))).Select(x => x.TrimEnd(".cs".ToCharArray())).ToList();
IEnumerable<string> queueList = GetTableName().Intersect(fileNames);
Connection = Factory.CreateConnection(); //连接服务器,即正在创建终结点。
channel = Connection.CreateModel();
channel.ExchangeDeclare(msgCenter.ExchangeName, "topic", true, false, null);
foreach (var queue in queueList)
{
channel.QueueDeclare(queue, true, false, false, null);//创建一个名称为kibaqueue的消息队列
channel.QueueBind(queue, msgCenter.ExchangeName, queue); // 绑定队列至交换机
//chanel.QueueDelete(tableName, false, false); //清空全部队列
Task.Factory.StartNew(() =>
{
var page = GetPageParams(queue);
GetDataTable(queue, page);
});
}
}
/// <summary>
/// 获取oracle数据库所有用户表
/// </summary>
/// <returns></returns>
public IEnumerable<string> GetTableName()
{
return dbContextO.Ado.Query<string>("select table_name from user_tables").AsEnumerable();
}
/// <summary>
/// 递归获取文件夹目录下所有文件名
/// </summary>
/// <param name="dir">遍历文件夹</param>
/// <param name="res">返回结果</param>
/// <returns></returns>
public List<string> GetFilesName(DirectoryInfo dir, List<string> res = null)
{
if (res == null)
{
res = new List<string>();
}
// 添加当前目录文件
FileInfo[] finfo = dir.GetFiles();
for (int i = 0; i < finfo.Length; i++)
{
res.Add(finfo[i].Name);
}
// 查找是否有下一级目录
var deepDir = dir.GetDirectories();
// 有,递归调用
if (deepDir.Length > 0)
{
foreach (var item in deepDir)
{
res = GetFilesName(item, res);
}
}
// 无,返回
return res;
}
/// <summary>
/// 格式化新旧表属性
/// </summary>
/// <param name="dir">遍历文件夹</param>
/// <param name="res">返回结果</param>
/// <returns></returns>
public DataTable FormatObject(DataTable table, List<string> res = null)
{
List<string> list = new List<string>();
for (int i = 0; i < table.Columns.Count; i++)
{
list.Add(table.Columns[i].ColumnName);
}
Type type = Assembly.Load("Models").GetTypes().FirstOrDefault(t => t.Name == table.TableName);
if(type != null)
{
PropertyInfo[] properinfos = type.GetProperties();
foreach (var item in properinfos)
{
if (item.Name != "IsChecked" && item.Name != "UpdateColumns")
{
if (!list.Contains(item.Name))
{
try
{
table.Columns.Add(item.Name, item.PropertyType);
}
catch (Exception)
{
table.Columns.Add(item.Name, item.PropertyType.GenericTypeArguments[0]);
}
}
}
}
}
return table;
}
/// <summary>
/// 获取文件索引
/// </summary>
/// <param name="tableName"></param>
/// <returns></returns>
public PageParams GetPageParams(string tableName)
{
string filePath = $"{DirectoryPath}/{tableName}.txt";
if (!Directory.Exists(DirectoryPath))
{
Directory.CreateDirectory(DirectoryPath);
}
if (!File.Exists(filePath))
{
File.CreateText(filePath).Dispose();
File.WriteAllText(filePath, "PageIndex:1, PageSize:100");
}
string pageString = File.ReadAllText(filePath);
return new PageParams()
{
PageIndex = Convert.ToInt32(Regex.Match(pageString, "PageIndex:\\d+").Value.Split(":").Last()),
PageSize = Convert.ToInt32(Regex.Match(pageString, "PageSize:\\d+").Value.Split(":").Last())
};
}
/// <summary>
/// 读取表数据
/// </summary>
/// <param name="tableName">表名</param>
/// <returns></returns>
public async void GetDataTable(string tableName, PageParams pageParams)
{
var table= await getTable(tableName, pageParams);
int rowsCount = table.Rows.Count;
int count = rowsCount;
// 数量与分页大小相同,证明表还有数据没有读完
while (count != 0)
{
string filePath = $"{DirectoryPath}/{tableName}.txt";
if (File.Exists(filePath))
{
string pageString = "";
using (StreamReader sr = new StreamReader(filePath))
{
pageString = sr.ReadToEnd();
}
using (StreamWriter sw = new StreamWriter(filePath)) {
pageParams.PageIndex = Convert.ToInt32(Regex.Match(pageString, "PageIndex:\\d+").Value.Split(":").Last()) + 1;
pageParams.PageSize = Convert.ToInt32(Regex.Match(pageString, "PageSize:\\d+").Value.Split(":").Last());
sw.Write($"PageIndex:{pageParams.PageIndex}, PageSize:{pageParams.PageSize}");
sw.Flush();
}
}
count = table.Rows.Count;
if (count > 0)
{
string json = JsonConvert.SerializeObject(table);
//var insertSql = GenerateSql(json, tableName);
//int result = dbContextM.Ado.ExecuteNonQuery(insertSql);
// 发送
msgCenter.Content = json;
msgCenter.Property = channel.CreateBasicProperties();
msgCenter.Property.DeliveryMode = 2;
msgCenter.MsgTypeName = tableName;
await MsgSender(msgCenter);
var methods = msgCenter.Property.GetType().GetMethods();
foreach (var method in methods)
{
try
{
method.Invoke(null, null);
}
catch (Exception)
{
Console.WriteLine("报错啦!");
}
}
}
table = null;
System.GC.Collect();
table = await getTable(tableName, pageParams);
Thread.Sleep(1000);
}
}
/// <summary>
/// 获取表格数据
/// </summary>
/// <param name="tableName"></param>
/// <param name="pageParams"></param>
/// <returns></returns>
async Task<DataTable> getTable(string tableName,PageParams pageParams)
{
int startIndex = (pageParams.PageIndex - 1) * pageParams.PageSize;
int endIndex = pageParams.PageIndex * pageParams.PageSize;
string pageSql = $"select * from {tableName} where rowid in (select rid from (select rownum rn,rowid rid from {tableName}) where rn > {startIndex} and rn <= {endIndex})";
var table = await dbContextO.Ado.ExecuteDataTableAsync(pageSql);
if (tableName == "JGZHXY")
{
table.TableName = "JGZHXX";
}
else
{
table.TableName = tableName;
}
table = FormatObject(table);
for (int i = 0; i < table.Rows.Count; i++)
{
for (int j = 0; j < table.Columns.Count; j++)
{
if (string.IsNullOrWhiteSpace(table.Rows[i][table.Columns[j]].ToString()))
{
if (table.Columns[j].DataType == typeof(DateTime?) || table.Columns[j].DataType == typeof(DateTime))
{
table.Rows[i][table.Columns[j].ColumnName] = new DateTime(2000, 1, 1);
}
else if (table.Columns[j].DataType == typeof(char))
{
table.Rows[i][table.Columns[j].ColumnName] = '0';
}
else if (table.Columns[j].DataType == typeof(byte[]))
{
table.Rows[i][table.Columns[j].ColumnName] = Encoding.UTF8.GetBytes("54088");
}
else if (table.Columns[j].DataType == typeof(Decimal))
{
table.Rows[i][table.Columns[j].ColumnName] = 123.45;
}
else
{
table.Rows[i][table.Columns[j].ColumnName] = "0";
if (table.Columns[j].ColumnName.ToUpper() == "tenant_id".ToUpper())
{
table.Rows[i][table.Columns[j].ColumnName] = "0";
}
if (table.Columns[j].ColumnName.ToUpper() == "xzqh_id".ToUpper())
{
table.Rows[i][table.Columns[j].ColumnName] = "0";
}
// XMTDSYZ表 ZZSJ字段用的string 但是新数据库用的mysql 有则取最后一条
if (tableName == "XMTDSYZ" && table.Columns[j].ColumnName == "ZZSJ" && !string.IsNullOrWhiteSpace(table.Rows[i][table.Columns[j]].ToString()))
{
table.Rows[i][table.Columns[j].ColumnName] = table.Rows[i][table.Columns[j].ColumnName].ToString().Split(',').Last();
}
}
}
}
}
return table;
}
/// <summary>
/// 读取JSON文件
/// </summary>
/// <param name="key">JSON文件中的key值</param>
/// <returns>JSON文件中的value值</returns>
public static string Readjson(string key)
{
string jsonfile = "../../../appsetting.json";//JSON文件路径
using (System.IO.StreamReader file = System.IO.File.OpenText(jsonfile))
{
using (JsonTextReader reader = new JsonTextReader(file))
{
JObject o = (JObject)JToken.ReadFrom(reader);
var value = o[key].ToString();
return value;
}
}
}
#region 消息队列
/// <summary>
/// 消息队列发送服务
/// </summary>
public Task MsgSender(MsgCenter msgCenter)
{
channel.BasicPublish(msgCenter.ExchangeName, msgCenter.MsgTypeName, msgCenter.Property, Encoding.UTF8.GetBytes(msgCenter.Content)); //生产消息
return Task.CompletedTask;
}
#endregion
}
}
消息接收:
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using OracleToMySQL.Common;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace CustomsMQ
{
public class Custom
{
public IModel channel { get; set; }
public EventingBasicConsumer customer { get; set; }
}
public class RabbitMQCutsom
{
//定义一个私有成员变量,用于Lock
IEnumerable<string> names;
private static object lockobj = new object();
private IFreeSql dbContextM = StaticVariable.DBContext[StaticVariable.MySql];
private Dictionary<string, Custom> Channel = new Dictionary<string, Custom>();
IConnection Connection = new ConnectionFactory()
{
HostName = "localhost",
UserName = "guest",
Password = "guest"
}.CreateConnection();
string Exchange = "myExchange";
public void Run()
{
RabbitMQCutsom services = new RabbitMQCutsom();
names = services.getNameList().Select(x => x.ToUpper());
IModel channel = Connection.CreateModel(); // 创建连接
foreach (var tableName in names)
{
#region 初始化消费者
channel.ExchangeDeclare(Exchange, "topic", true, false, null);
channel.QueueBind(tableName, Exchange, tableName);
#endregion
}
var consumer = new EventingBasicConsumer(channel); // 消费者
consumer.Received += (ch, ea) =>
{
lock (lockobj)
{
string errMsg = string.Empty;
string message = Encoding.Default.GetString(ea.Body.ToArray());
if (!string.IsNullOrWhiteSpace(message))
{
//InsertData(message, msgCenter.MsgTypeName, ref errMsg);
// 消费完成
//if (string.IsNullOrWhiteSpace(errMsg))
//{
// Console.WriteLine($"写入成功:{msgCenter.MsgTypeName}");
//}
if (!string.IsNullOrWhiteSpace(message))
{
//通过反射跨类库拿实体
Assembly assembly = Assembly.LoadFrom("Models");
Type instanceType = assembly.GetType($"GD.NP.FDCSCJG.Models.{ea.RoutingKey}");
var instanceTypes = Type.GetType($"System.Collections.Generic.List`1[[{instanceType.AssemblyQualifiedName}]]");
var instanceDatas = Newtonsoft.Json.JsonConvert.DeserializeObject(message, instanceTypes);
List<object> objList = ((IEnumerable<object>)instanceDatas).ToList();
var properties = objList[0].GetType().GetProperties();
foreach (var obj in objList)
{
foreach (var property in properties)
{
if (property.Name == "SFYC" || property.Name == "SFDT" || property.Name == "SFTY" || property.Name == "SFZX")
{
property.SetValue(obj, property.GetValue(obj).ToString().ElementAt(0).ToString());
}
else if (property.Name == "ZZSJ")
{
property.SetValue(obj, property.GetValue(obj).ToString().Split(',').ElementAt(0));
}
else
{
property.SetValue(obj, property.GetValue(obj));
}
}
}
//通过反射拿方法
var insertMethod = dbContextM.GetType().GetMethods()
.Where(o => o.Name == "Insert"
&& o.GetParameters().Where(p => p.ParameterType.Name == "List`1").ToList().Count == 1
&& o.GetGenericArguments().Length == 1
).FirstOrDefault();
var insertGenericMethod = insertMethod.MakeGenericMethod(instanceType);
var iInsert = insertGenericMethod.Invoke(dbContextM, new object[] { instanceDatas });
var iInsertType = iInsert.GetType();
var executeAffrowsMethod = iInsertType.GetMethods()
.Where(o => o.Name == "ExecuteAffrows" && o.GetGenericArguments().Length == 0)
.FirstOrDefault();
try
{
var resultInsert = executeAffrowsMethod.Invoke(iInsert, null);
Console.WriteLine($"{ea.RoutingKey}成功!");
}
catch (Exception ex)
{
Console.WriteLine($"{ea.RoutingKey}插入失败了:{ex.Message}");
}
//channel.BasicAck(ea.DeliveryTag, false);
}
}
// 有的数据之前已经插入过表 不需要确认 以免造成消息积压
//Channel[msgCenter.MsgTypeName].channel.BasicAck(ea.DeliveryTag, false);
message = null;
errMsg = null;
Thread.Sleep(1000);
System.GC.Collect();
}
};
//启动消费者 设置为手动应答消息
foreach (var tableName in names)
{
channel.BasicConsume(tableName, true, consumer);
}
Console.ReadKey();
}
/// <summary>
/// 获取数据库所有表名
/// </summary>
/// <returns></returns>
public List<string> getNameList()
{
return dbContextM.Ado.Query<string>("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='gd_bdcfc_fcscjg'");
}
}
}