ZhiYeJianKang_PeiXun/cyqdata-master/DAL/Conn/ConnObject.cs
2025-02-20 15:41:53 +08:00

253 lines
8.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Web;
using CYQ.Data.Tool;
namespace CYQ.Data
{
/// <summary>
/// 一个数据库对像实例:集合了主从备三种
/// </summary>
internal partial class ConnObject
{
public ConnBean Master;
public ConnBean BackUp;
public MList<ConnBean> Slave = new MList<ConnBean>();
/// <summary>
/// 主备互换位置。
/// </summary>
internal void InterChange()
{
if (BackUp != null)
{
ConnBean middle = Master;
Master = BackUp;
BackUp = middle;
}
}
static int index = -1;
static readonly object o = new object();
public ConnBean GetSlave()
{
if (Slave.Count > 0)
{
lock (o)
{
if (index == -1)
{
index = new Random().Next(Slave.Count);
}
if (index >= Slave.Count)//2
{
index = 0;
}
ConnBean slaveBean = Slave[index];
index++;
if (slaveBean.IsOK)//链接正常,则返回。
{
return slaveBean;
}
else if (Slave.Count > 1)
{
//int i = index + 1;//尝试一下个,。
for (int i = index + 1; i < Slave.Count + 1; i++)
{
if (i == Slave.Count)
{
i = 0;
}
if (i == index) { break; }
if (Slave[i].IsOK)
{
return Slave[i];
}
}
}
//从全部挂了,返回主
if (Master != null && Master.IsOK)
{
return Master;
}
else if (BackUp != null && BackUp.IsOK)
{
return BackUp;
}
}
}
return null;
}
/// <summary>
/// 设置临时仅允许访问主库默认10秒
/// </summary>
public void SetFocusOnMaster()
{
if (Slave.Count > 0)
{
string id = StaticTool.GetMasterSlaveKey();//获取当前的标识
Cache.DistributedCache.Local.Set(id, 1, AppConfig.DB.MasterSlaveTime / 60.0);
}
}
public bool IsAllowSlave()
{
if (Slave.Count == 0) { return false; }
string id = StaticTool.GetMasterSlaveKey();//获取当前的标识
return !Cache.DistributedCache.Local.Contains(id);
}
}
internal partial class ConnObject
{
/// <summary>
/// 所有链接的对象集合
/// </summary>
private static MDictionary<string, ConnObject> connDicCache = new MDictionary<string, ConnObject>(StringComparer.OrdinalIgnoreCase);
internal static ConnObject Create(string connNameOrString)
{
connNameOrString = string.IsNullOrEmpty(connNameOrString) ? AppConfig.DB.DefaultConn : connNameOrString;
if (connNameOrString.EndsWith("_Bak"))
{
connNameOrString = connNameOrString.Replace("_Bak", "");
}
if (connDicCache.ContainsKey(connNameOrString))
{
return connDicCache[connNameOrString];
}
ConnBean cbMaster = ConnBean.Create(connNameOrString);
if (cbMaster == null)
{
#region Conn配置
string errMsg = string.Format("Can't find the connection key '{0}' from connectionStrings config section !", connNameOrString);
if (connNameOrString == AppConfig.DB.DefaultConn)
{
Error.Throw(errMsg);
}
else
{
ConnBean cb = ConnBean.Create(AppConfig.DB.DefaultConn); // 这里切到了默认链接导致ConnName变成了默认
if (cb != null)
{
cbMaster = cb.Clone();//获取默认的值。
}
else
{
Error.Throw(errMsg);
}
}
#endregion
}
ConnObject co = new ConnObject();
co.Master = cbMaster;
#region
if (connNameOrString != null && connNameOrString.Length < 32 && !connNameOrString.Trim().Contains(" ")) // 为configKey
{
ConnBean coBak = ConnBean.Create(connNameOrString + "_Bak");
if (coBak != null && coBak.ConnDataBaseType == cbMaster.ConnDataBaseType)
{
co.BackUp = coBak;
co.BackUp.IsBackup = true;
}
for (int i = 1; i < 10000; i++)
{
ConnBean cbSlave = ConnBean.Create(connNameOrString + "_Slave" + i);
if (cbSlave == null)
{
break;
}
cbSlave.IsSlave = true;
co.Slave.Add(cbSlave);
}
}
#endregion
if (!connDicCache.ContainsKey(connNameOrString) && co.Master.ConnName == connNameOrString) // 非一致的,由外面切换后再缓存
{
connDicCache.Set(connNameOrString, co);
}
return co;
}
public void SaveToCache(string key)
{
if (!connDicCache.ContainsKey(key))
{
connDicCache.Add(key, this);
}
}
public static void Clear()
{
connDicCache.Clear();
}
public static void Remove(string key)
{
connDicCache.Remove(key);
}
}
/// <summary>
/// 线程任务
/// </summary>
internal partial class ConnObject
{
static ConnObject()
{
ThreadBreak.AddGlobalThread(new ParameterizedThreadStart(CheckConnIsOk));//主从链接的检测机制。
}
/// <summary>
/// 定时检测异常的链接是否恢复。
/// </summary>
/// <param name="threadID"></param>
public static void CheckConnIsOk(object threadID)
{
System.Diagnostics.Debug.WriteLine("ConnObject.CheckConnIsOk on Thread :" + threadID);
while (true)
{
Thread.Sleep(1000);
if (connDicCache.Count > 0)
{
try
{
string[] items = new string[connDicCache.Count];
connDicCache.Keys.CopyTo(items, 0);
foreach (string key in items)
{
ConnObject obj = connDicCache[key];
if (obj != null)
{
if (!obj.Master.IsOK)
{
if (obj.Master.ConnName == obj.Master.ConnString)
{
connDicCache.Remove(key);//移除错误的链接。
continue;
}
obj.Master.TryTestConn();
}
if (obj.BackUp != null && !obj.BackUp.IsOK) { obj.BackUp.TryTestConn(); }
if (obj.Slave != null && obj.Slave.Count > 0)
{
for (int i = 0; i < obj.Slave.Count; i++)
{
if (!obj.Slave[i].IsOK)
{
obj.Slave[i].TryTestConn();
}
}
}
}
}
items = null;
}
catch
{
}
}
}
}
}
}