[英]Entity Framework baseline integrity
I am working with Entity Framework database first, and I have a table that stores historical values using baseline ids. 我首先使用Entity Framework数据库,并且有一个表使用基线ID存储历史值。 We store parent/child links on this table using the baseline id.
我们使用基线ID在此表上存储父/子链接。 The following columns makeup this design:-
以下专栏对此设计进行了补充:-
Example data for clarity 为清楚起见示例数据
Id BaselineId ParentBaselineId Latest
1 1 NULL 0
2 1 NULL 1
3 2 1 0
4 2 1 1
This shows two items, each with two revisions. 这显示了两个项目,每个项目都有两个修订版本。 Baseline 1 is the parent of baseline 2.
基准1是基准2的父级。
My issue is that for the reasons listed below I lookup the next available baseline in C# and manually specify the BaselineId/ParentBaselineId to be saved. 我的问题是,出于下面列出的原因,我在C#中查找了下一个可用基线,并手动指定了要保存的BaselineId / ParentBaselineId。 When two users trigger this method at the same time, they save the same Baseline ids, as the save does not complete before the second users looks up the next available baseline id.
当两个用户同时触发此方法时,他们将保存相同的基准ID,因为在第二个用户查找下一个可用的基准ID之前,保存尚未完成。
What measures can I take to ensure that the same baseline won't be used by two users running the method at the same time? 我应该采取什么措施来确保两个用户同时运行该方法不会使用相同的基线?
My C# looks something like this 我的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();
}
Using @Steve Greene 's suggestion, I was able to use an SQL sequence. 根据@Steve Greene的建议,我可以使用SQL序列。 After creating a new sequence in my database and setting the start value to match my existing data, I updated my code to the following.
在数据库中创建新序列并设置起始值以匹配现有数据后,我将代码更新为以下内容。
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();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.