diff --git a/Action/MAction.cs b/Action/MAction.cs
index 15b1a268..c1d29547 100644
--- a/Action/MAction.cs
+++ b/Action/MAction.cs
@@ -177,6 +177,16 @@ public int RecordsAffected
}
}
///
+ /// 是否事务进行中
+ ///
+ public bool IsTransation
+ {
+ get
+ {
+ return dalHelper.IsOpenTrans;
+ }
+ }
+ ///
/// Command Timeout[seconds]
///命令超时设置[单位秒]
///
diff --git a/Action/MProc.cs b/Action/MProc.cs
index 77da4d73..55a2df35 100644
--- a/Action/MProc.cs
+++ b/Action/MProc.cs
@@ -127,6 +127,16 @@ public int RecordsAffected
}
}
///
+ /// 鏄惁浜嬪姟杩涜涓
+ ///
+ public bool IsTransation
+ {
+ get
+ {
+ return dalHelper.IsOpenTrans;
+ }
+ }
+ ///
/// The database connection string
///鏁版嵁搴撻摼鎺ュ瓧绗︿覆
///
diff --git a/DAL/Conn/ConnObject.cs b/DAL/Conn/ConnObject.cs
index 5acbcdc2..6eb5c637 100644
--- a/DAL/Conn/ConnObject.cs
+++ b/DAL/Conn/ConnObject.cs
@@ -85,59 +85,17 @@ public void SetFocusOnMaster()
{
if (Slave.Count > 0)
{
- string id = GetIdentity();//获取当前的标识
+ string id = StaticTool.GetMasterSlaveKey();//获取当前的标识
Cache.CacheManage.LocalInstance.Set(id, 1, AppConfig.DB.MasterSlaveTime / 60.0);
}
}
public bool IsAllowSlave()
{
if (Slave.Count == 0) { return false; }
- string id = GetIdentity();//获取当前的标识
+ string id = StaticTool.GetMasterSlaveKey();//获取当前的标识
return !Cache.CacheManage.LocalInstance.Contains(id);
}
- private string GetIdentity()
- {
- string id = string.Empty;
- if (HttpContext.Current != null)
- {
- if (HttpContext.Current.Session != null)
- {
- id = HttpContext.Current.Session.SessionID;
- }
- else if (HttpContext.Current.Request["Token"] != null)
- {
- id = HttpContext.Current.Request["Token"];
- }
- else if (HttpContext.Current.Request.Headers["Token"] != null)
- {
- id = HttpContext.Current.Request.Headers["Token"];
- }
- else if (HttpContext.Current.Request["MasterSlaveid"] != null)
- {
- id = HttpContext.Current.Request["MasterSlaveid"];
- }
- if (string.IsNullOrEmpty(id))
- {
- HttpCookie cookie = HttpContext.Current.Request.Cookies["MasterSlaveid"];
- if (cookie != null)
- {
- id = cookie.Value;
- }
- else
- {
- id = Guid.NewGuid().ToString().Replace("-", "");
- cookie = new HttpCookie("MasterSlaveid", id);
- cookie.Expires = DateTime.Now.AddMonths(1);
- HttpContext.Current.Response.Cookies.Add(cookie);
- }
- }
- }
- if (string.IsNullOrEmpty(id))
- {
- id = DateTime.Now.Minute + Thread.CurrentThread.ManagedThreadId.ToString();
- }
- return "MasterSlave_" + id;
- }
+
}
internal partial class ConnObject
@@ -242,14 +200,14 @@ public static void CheckConnIsOk(object threadid)
ConnObject obj = connDicCache[key];
if (obj != null)
{
- if (!obj.Master.IsOK)
+ if (!obj.Master.IsOK)
{
if (obj.Master.ConnName == obj.Master.ConnString)
{
connDicCache.Remove(key);//移除错误的链接。
continue;
}
- obj.Master.TryTestConn();
+ obj.Master.TryTestConn();
}
if (obj.BackUp != null && !obj.BackUp.IsOK) { obj.BackUp.TryTestConn(); }
if (obj.Slave != null && obj.Slave.Count > 0)
diff --git a/DAL/DalBase.cs b/DAL/DalBase.cs
index ca4a7c85..825c1fcf 100644
--- a/DAL/DalBase.cs
+++ b/DAL/DalBase.cs
@@ -7,6 +7,7 @@
using CYQ.Data.Tool;
using System.Data.SqlTypes;
using System.Threading;
+using CYQ.Data.Orm;
namespace CYQ.Data
@@ -478,6 +479,10 @@ public virtual bool AddParameters(string parameterName, object value, DbType dbT
{
parameterName = parameterName.Substring(0, 1) == Pre.ToString() ? parameterName : Pre + parameterName;
}
+ if (Com == null)
+ {
+ return false;
+ }
if (Com.Parameters.Contains(parameterName))//宸茬粡瀛樺湪锛屼笉娣诲姞
{
return false;
@@ -789,6 +794,11 @@ internal void WriteError(string err)
public void Dispose()
{
+ string key = StaticTool.GetTransationKey(UsingConnBean.ConnName);
+ if (DBFast.HasTransation(key))
+ {
+ return;//鍏ㄥ眬浜嬪姟鐢卞叏灞鎺у埗锛堝叏灞浜嬪姟浼氬湪绉婚櫎key鍚庨噸鏂拌皟鐢級銆
+ }
if (_con != null)
{
CloseCon();
diff --git a/DAL/DalCreate.cs b/DAL/DalCreate.cs
index 9fcdc8f7..bed929d6 100644
--- a/DAL/DalCreate.cs
+++ b/DAL/DalCreate.cs
@@ -4,6 +4,7 @@
using CYQ.Data.Tool;
using System.Threading;
using System.IO;
+using CYQ.Data.Orm;
namespace CYQ.Data
@@ -11,7 +12,7 @@ namespace CYQ.Data
///
/// 数据库类型操作类
///
- internal class DalCreate
+ internal static class DalCreate
{
//private const string SqlClient = "System.Data.SqlClient";
//private const string OleDb = "System.Data.OleDb";
@@ -24,10 +25,48 @@ internal class DalCreate
//private const string XmlClient = "CYQ.Data.XmlClient";
//private const string XHtmlClient = "CYQ.Data.XHtmlClient";
+ ///
+ /// 全局存档,是为了用单例来实现全局事务。
+ ///
+ private static MDictionary dalBaseDic = new MDictionary();
+ public static DalBase Get(string key)
+ {
+ if (dalBaseDic.ContainsKey(key))
+ {
+ return dalBaseDic[key];
+ }
+ return null;
+ }
+ public static bool Remove(string key)
+ {
+ return dalBaseDic.Remove(key);
+ }
///
/// 简单工厂(Factory Method)
///
public static DalBase CreateDal(string connNameOrString)
+ {
+ string key = StaticTool.GetTransationKey(connNameOrString);
+ //检测是否开启了全局事务;
+ bool isTrans = DBFast.HasTransation(key);
+ if (isTrans)
+ {
+ if (dalBaseDic.ContainsKey(key))
+ {
+ return dalBaseDic[key];
+ }
+
+ }
+ DalBase dal = CreateDalBase(connNameOrString);
+ if (isTrans)
+ {
+ dal.TranLevel = DBFast.GetTransationLevel(key);
+ dal.IsOpenTrans = true;
+ dalBaseDic.Add(key, dal);
+ }
+ return dal;
+ }
+ private static DalBase CreateDalBase(string connNameOrString)
{
//ABCConn
DalBase db = GetDalBaseBy(ConnObject.Create(connNameOrString));
@@ -43,9 +82,7 @@ public static DalBase CreateDal(string connNameOrString)
}
}
return db;
-
}
-
private static DalBase GetDalBaseBy(ConnObject co)
{
DataBaseType dalType = co.Master.ConnDalType;
diff --git a/Orm/DBFast.cs b/Orm/DBFast.cs
index ceb2892c..4483eef2 100644
--- a/Orm/DBFast.cs
+++ b/Orm/DBFast.cs
@@ -4,6 +4,9 @@
using CYQ.Data.Table;
using CYQ.Data.SQL;
using CYQ.Data.Tool;
+using System.Web;
+using System.Threading;
+using System.Data;
namespace CYQ.Data.Orm
@@ -13,6 +16,73 @@ namespace CYQ.Data.Orm
///
public static class DBFast
{
+ ///
+ /// 当前 用户 是否开启了全局事务
+ ///
+ ///
+ internal static bool HasTransation(string key)
+ {
+ return TransationKeys.ContainsKey(key);
+ }
+ internal static IsolationLevel GetTransationLevel(string key)
+ {
+ if (TransationKeys.ContainsKey(key))
+ {
+ return TransationKeys[key];
+ }
+ return IsolationLevel.ReadCommitted;
+ }
+ ///
+ /// 存档事务的标识
+ ///
+ public static MDictionary TransationKeys = new MDictionary();
+ ///
+ /// 开启事务 (Web 状态下以(Session+线程ID)为单位,其它状态下仅以线程ID为单位)
+ /// 如果已存在事务(则返回false)
+ ///
+ public static bool BeginTransation(string conn)
+ {
+ return BeginTransation(conn, IsolationLevel.ReadCommitted);
+ }
+ public static bool BeginTransation(string conn, IsolationLevel level)
+ {
+ string key = StaticTool.GetTransationKey(conn);
+ if (!TransationKeys.ContainsKey(key))
+ {
+ TransationKeys.Add(key, level);
+ }
+ return false;
+ }
+ ///
+ /// 提交事务
+ ///
+ public static bool EndTransation(string conn)
+ {
+ string key = StaticTool.GetTransationKey(conn);
+ TransationKeys.Remove(key);
+ DalBase dal = DalCreate.Get(key);
+ if (dal != null && dal.EndTransaction())//如果事务回滚了,
+ {
+ dal.Dispose();
+ return DalCreate.Remove(key);
+ }
+ return false;
+ }
+ ///
+ /// 事务回滚
+ ///
+ public static bool RollBack(string conn)
+ {
+ string key = StaticTool.GetTransationKey(conn);
+ TransationKeys.Remove(key);
+ DalBase dal = DalCreate.Get(key);
+ if (dal != null && dal.RollBack())
+ {
+ dal.Dispose();
+ return DalCreate.Remove(key);
+ }
+ return false;
+ }
///
/// 查找单条记录
///
diff --git a/Orm/OrmBaseInfo.cs b/Orm/OrmBaseInfo.cs
index 4fcb7c73..975fecec 100644
--- a/Orm/OrmBaseInfo.cs
+++ b/Orm/OrmBaseInfo.cs
@@ -30,6 +30,16 @@ public int RecordsAffected
}
}
///
+ /// 鏄惁浜嬪姟杩涜涓
+ ///
+ public bool IsTransation
+ {
+ get
+ {
+ return _Action.IsTransation;
+ }
+ }
+ ///
/// 鑾峰彇 鏁版嵁搴撶殑 琛ㄥ悕
///
public string TableName
diff --git a/Orm/SimpleOrmBase.cs b/Orm/SimpleOrmBase.cs
index 1129feec..10622186 100644
--- a/Orm/SimpleOrmBase.cs
+++ b/Orm/SimpleOrmBase.cs
@@ -613,7 +613,7 @@ private void GetValueFromEntity()
///
public void Dispose()
{
- if (Action != null)
+ if (Action != null && !Action.IsTransation)//ORM的事务,由全局控制,不在这里释放链接。
{
Action.Dispose();
}
diff --git a/Tool/StaticTool.cs b/Tool/StaticTool.cs
index 47329fef..2dec55d3 100644
--- a/Tool/StaticTool.cs
+++ b/Tool/StaticTool.cs
@@ -6,6 +6,8 @@
using CYQ.Data.Table;
using CYQ.Data.SQL;
using System.IO;
+using System.Web;
+using System.Threading;
namespace CYQ.Data.Tool
@@ -26,11 +28,6 @@ internal static string ToGuidByteString(string guid)
return BitConverter.ToString(new Guid(guid).ToByteArray()).Replace("-", "");
}
-
-
-
-
- #region 将字符串变HashKey
static MDictionary hashKeyCache = new MDictionary(32);
internal static string GetHashKey(string sourceString)
{
@@ -57,7 +54,78 @@ internal static string GetHashKey(string sourceString)
return sourceString;
}
}
- #endregion
-
+ ///
+ /// 用于标识(以用户为单位)的 主从 的唯一标识
+ ///
+ ///
+ public static string GetMasterSlaveKey()
+ {
+ string id = string.Empty;
+ if (HttpContext.Current != null)
+ {
+ if (HttpContext.Current.Session != null)
+ {
+ id = HttpContext.Current.Session.SessionID;
+ }
+ else if (HttpContext.Current.Request["Token"] != null)
+ {
+ id = HttpContext.Current.Request["Token"];
+ }
+ else if (HttpContext.Current.Request.Headers["Token"] != null)
+ {
+ id = HttpContext.Current.Request.Headers["Token"];
+ }
+ else if (HttpContext.Current.Request["MasterSlaveid"] != null)
+ {
+ id = HttpContext.Current.Request["MasterSlaveid"];
+ }
+ if (string.IsNullOrEmpty(id))
+ {
+ HttpCookie cookie = HttpContext.Current.Request.Cookies["MasterSlaveid"];
+ if (cookie != null)
+ {
+ id = cookie.Value;
+ }
+ else
+ {
+ id = Guid.NewGuid().ToString().Replace("-", "");
+ cookie = new HttpCookie("MasterSlaveid", id);
+ cookie.Expires = DateTime.Now.AddMonths(1);
+ HttpContext.Current.Response.Cookies.Add(cookie);
+ }
+ }
+ }
+ if (string.IsNullOrEmpty(id))
+ {
+ id = DateTime.Now.Minute + Thread.CurrentThread.ManagedThreadId.ToString();
+ }
+ return "MasterSlave_" + id;
+ }
+ ///
+ /// 用于标识(以用户为单位)的 全局事务 的唯一标识
+ ///
+ public static string GetTransationKey(string conn)
+ {
+ string key = Thread.CurrentThread.ManagedThreadId.ToString();
+ if (HttpContext.Current != null)
+ {
+ string id = string.Empty;
+ if (HttpContext.Current.Session != null)
+ {
+ id = HttpContext.Current.Session.SessionID;
+ }
+ else if (HttpContext.Current.Request["Token"] != null)
+ {
+ id = HttpContext.Current.Request["Token"];
+ }
+ else if (HttpContext.Current.Request.Headers["Token"] != null)
+ {
+ id = HttpContext.Current.Request.Headers["Token"];
+ }
+ key = id + key;
+ }
+ int hash = ConnBean.GetHashCode(conn);
+ return "Transation_" + key + hash;
+ }
}
}
diff --git "a/\346\233\264\346\226\260\350\256\260\345\275\225.txt" "b/\346\233\264\346\226\260\350\256\260\345\275\225.txt"
index be26614c..1ecf95db 100644
--- "a/\346\233\264\346\226\260\350\256\260\345\275\225.txt"
+++ "b/\346\233\264\346\226\260\350\256\260\345\275\225.txt"
@@ -796,4 +796,5 @@
581:NoSqlAction:文本数据库机制内部调整、查询优化。(2019-04-29)
582:Aop、AutoCache:自动缓存机制小调整,除了原有的全局IsAutoCache全局初始化控制外,Aop参数可二次强制控制。(2019-04-29)
583:增加 JsonIgnore 属性(标识不输出Json的字段)、SimpleOrmBase、OrmBase增加BaseInfo属性可获得详细信息(2019-04-29)
-584:优化Json与Xml互转机制(2019-04-29)
\ No newline at end of file
+584:优化Json与Xml互转机制(2019-04-29)
+585:DBFast 增加全局事务机制【最近因 Gemini.Workflow,因此对ORM实体这一块进行内部机制大升级】(2019-05-04)
\ No newline at end of file