我首先使用实体框架数据库,我有一个使用基线ids存储历史值的表。我们使用基线id在此表中存储父/子链接。以下列构成此设计:-
示例数据以提高清晰度
Id BaselineId ParentBaselineId Latest
1 1 NULL 0
2 1 NULL 1
3 2 1 0
4 2 1 1
这显示了两个项目,每个项目有两个修订。基线1是基线2的父级。
我的问题是,由于下面列出的原因,我在C#中查找下一个可用的基线,并手动指定要保存的BaselineId/ParentBaselineId。当两个用户同时触发此方法时,他们保存相同的基线id,因为保存在第二个用户查找下一个可用的基线id之前没有完成。
我可以采取什么措施来确保同时运行该方法的两个用户不会使用相同的基线?
我的C#看起来像这样
using (var tx = new TransactionScope())
{
using (var context = new DbContext(connectionString))
{
int baseline = context.MyTable.Max(e => e.BaselineId);
context.MyTable.Add(new MyTable() {BaselineId = baseline + 1, Latest = true});
context.MyTable.Add(new MyTable() { BaselineId = baseline + 2, ParentBaselineId = baseline + 1, Latest = true });
context.SaveChanges();
}
tx.Complete();
}
发布于 2017-02-20 08:51:32
使用@Steve的建议,我能够使用SQL序列。在我的数据库中创建了一个新序列并设置了与现有数据匹配的开始值之后,我将代码更新如下。
public long NextBaseline(DbContext context)
{
DataTable dt = new DataTable();
var conn = context.Database.Connection;
var connectionState = conn.State;
try
{
if (connectionState != ConnectionState.Open)
conn.Open();
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "SELECT NEXT VALUE FOR MySequence;";
using (var reader = cmd.ExecuteReader())
{
dt.Load(reader);
}
}
}
catch (Exception ex)
{
throw new HCSSException(ex.Message, ex);
}
finally
{
if (connectionState != ConnectionState.Open)
conn.Close();
}
return Convert.ToInt64(dt.AsEnumerable().First().ItemArray[0]);
}
public void Save()
{
using (var tx = new TransactionScope())
{
using (var context = new DbContext(connectionString))
{
var parent = new MyTable() { BaselineId = NextBaseline(context), Latest = true };
var child = new MyTable() { BaselineId = NextBaseline(context), ParentBaselineId = parent.BaselineId, Latest = true }
context.MyTable.Add(parent);
context.MyTable.Add(child);
context.SaveChanges();
}
tx.Complete();
}
}
https://stackoverflow.com/questions/42299458
复制相似问题