简体   繁体   English

实体框架基准完整性

[英]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:- 以下专栏对此设计进行了补充:-

  • Id int (primary key - unique) ID int(主键-唯一)
  • BaselineId int (not unique, but does uniquely identity revisions of the same item) BaselineId int(不是唯一的,但是对同一项目进行唯一的身份修订)
  • ParentBaselineId int nullable (refers to the baseline of the linked entity, no FK) ParentBaselineId int可为空(指链接实体的基线,无FK)
  • Latest bit (indicated that this is the most recent baseline in a series) 最新位(指示这是系列中的最新基线)

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之前,保存尚未完成。

  • The method can add many items at once that must be linked together by baseline ids 该方法可以一次添加许多必须通过基准ID链接在一起的项目
  • This must be a single SQL transaction so it can rollback completely on error 这必须是单个SQL事务,以便可以在发生错误时完全回滚
  • SQL trigger cannot be used to set the baselines because they are needed ahead of time to indicate the relationships SQL触发器不能用于设置基线,因为需要提前使用基线来指示关系

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM