我首先使用Entity Framework数据库,并且我有一个使用基线ID存储历史值的表。我们使用基线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。当两个用户同时触发此方法时,它们会保存相同的Baseline 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();
}
答案 0 :(得分:0)
使用@Steve Greene的建议,我能够使用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();
}
}