DataLock - 数据锁、单据号码锁、并发锁(C#源码)
DataLock - 数据锁、单据号码锁、并发锁
一、DataLock说明
数据锁机制用于管理对共享资源的并发访问,确保数据的完整性和一致性。DataLock数据锁主要用于在多用户操作环境下,避免多用户并发操作,导致脏写、脏读以及脏数据形成。
二、应用场景
- 数据锁,用于处理特定的数据,比如用户A必须独占处理某种数据,执行数据锁后,用户B必须等待用户A处理完毕。
- 单据号码锁,用于生成唯一的单据号码,不会并发操作!
- 并发锁,处理有关并发方面的需求。
三、使用方法
3.1 数据锁标准使用方法
C# 全选
public string DoSomething()
{
//实例化锁
var dataLock = new DataLock(db_System, "LockName", "测试业务锁");
try
{
dataLock.SetLock(); //锁定
//
//在这里编写处理逻辑
//
dataLock.Release();//处理完成:释放锁
return "测试成功!";
}
catch (Exception ex)
{
dataLock.Release();
throw ex;
}
}
3.2 生成唯一的单据号码、流水号码
C# 全选
//获取最新的GroupNo,物流编号
public long GetNewGroupNo()
{
//单据号码锁
var dataLock = new DataLock(db_System, "LogisticGroup", "物流编号-单据号码锁");
try
{
dataLock.SetLock(); //锁定
long lastNo = GetLastGroupNo();//获取业务单据,最大的单据号码, MAX(NO)
long groupNo;
//第一次初始化锁
if (String.IsNullOrEmpty(dataLock.LockData.Data))
dataLock.LockData.Data = lastNo.ToString();
//获取数据锁最新的号码
groupNo = ConvertEx.ToLong(dataLock.LockData.Data);//字符串转long
if (groupNo == 0) groupNo = lastNo;
//若数据锁中的号码小于单据最大的号码
if (groupNo < lastNo) groupNo = lastNo;
groupNo++;//号码加1
dataLock.SetData(groupNo.ToString());//设置数据
dataLock.Release();//释放锁
return groupNo;
}
catch (Exception ex)
{
dataLock.Release();
throw ex;
}
}
四、DataLock 源码
C# 全选
/// <summary>
/// DataLock - 数据锁、单据号码锁、并发锁(C#源码)
/// </summary>
public class DataLock
{
private DbFramework _EF;
private string _lockName;
private string _note;
private string _token;
private int _MAX_TRY_COUNT = 10;
private sys_DataLock _Data = null;
public sys_DataLock LockData { get { return _Data; } }
/// <summary>
/// 构造器
/// </summary>
/// <param name="db">CSFramework.DB数据库组件</param>
/// <param name="lockName">数据锁名称</param>
/// <param name="note">备注</param>
/// <param name="maxTryCount">锁占用状态下, 尝试重新锁定的次数</param>
public DataLock(IDatabase db, string lockName, string note = null, int maxTryCount = 10)
{
_lockName = lockName;
_note = note;
_MAX_TRY_COUNT = maxTryCount;
_token = GetToken();//当前实例的token,重要!!!
_EF = new DbFramework(db);
}
/// <summary>
/// 是否锁定状态
/// </summary>
/// <returns></returns>
public bool IsLock()
{
if (_Data == null)
{
_Data = GetLock();
if (_Data == null) _Data = AddLock();//添加锁
}
return _Data.IsLock;
}
/// <summary>
/// 锁定
/// </summary>
public void SetLock()
{
//尝试锁定10次
for (int i = 1; i <= _MAX_TRY_COUNT; i++)
{
_Data = GetLock();//获取锁数据
if (_Data == null) _Data = AddLock();//添加锁
if (_Data.IsLock == false)
{
_Data.IsLock = true;
_Data.AccessTime = DateTime.Now;
_Data.AccessToken = _token; //当前token
_EF.UpdateObject<sys_DataLock>(_Data);
return; //设置锁成功
}
else
{
//已经是锁定状态,等待其他用户释放锁
Thread.Sleep(1000);
}
}
throw new Exception($"设置数据锁<{_lockName}>失败");
}
/// <summary>
/// 设置锁的关联数据
/// </summary>
/// <param name="data">关联数据</param>
/// <param name="note">备注</param>
public void SetData(string data, string note = null)
{
_Data.Data = data;
_Data.Note = String.IsNullOrEmpty(note) ? _Data.Note : note;
_Data.AccessTime = DateTime.Now;
//提交数据
//_EF.UpdateObject<sys_DataLock>(_Data);
_EF.UpdateObject<sys_DataLock>(_Data, null, null, new string[] { "Data", "Note", "AccessTime" });
}
/// <summary>
/// 释放锁, 只可释放自己的锁!!!根据token判断
/// </summary>
public void Release()
{
_Data.IsLock = false;
_Data.AccessTime = DateTime.Now;
_EF.UpdateObject<sys_DataLock>(_Data, new string[] { "AccessToken" });
}
private sys_DataLock AddLock()
{
sys_DataLock o = new sys_DataLock
{
LockName = this._lockName,
Note = this._note,
IsLock = false,//默认不锁定
AccessTime = DateTime.Now,
AccessToken = _token,//当前token
};
bool ok = _EF.AddObject(o);
if (ok)
return o;
else
throw new Exception("添加锁失败!");
}
private sys_DataLock GetLock()
{
return _EF.Select<sys_DataLock>("LockName", _lockName);//根据key获取锁
}
private string GetToken()
{
long result = 1;
int index = 1;
byte[] bs = Guid.NewGuid().ToByteArray();
foreach (byte b in bs)
{
result *= ((int)b + index * 2);
index++;
}
var hex = string.Format("{0:x}", result);
return hex;
}
}
五、sys_DataLock 表结构
C# 全选
/// <summary>
/// 数据锁的模型
/// </summary>
public class sys_DataLock
{
[IgnoreField]
public int isid { get; set; }
/// <summary>
/// 锁名称
/// </summary>
[KeyField]
public string LockName { get; set; }
/// <summary>
/// 是否锁定状态
/// </summary>
public bool IsLock { get; set; }
/// <summary>
/// 关联数据,自定义数据
/// </summary>
public string Data { get; set; }
/// <summary>
/// 备注信息
/// </summary>
public string Note { get; set; }
/// <summary>
/// 最新操作锁的时间
/// </summary>
public DateTime AccessTime { get; set; }
/// <summary>
/// 当前访问锁的用户标识(token)
/// </summary>
public string AccessToken { get; set; }
}
六、依赖项目
CSFramework.DB
https://www.cscode.net/archive/csframework.db/1630589248.html
版权声明:本文为开发框架文库发布内容,转载请附上原文出处连接
NewDoc C/S框架网