首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >实体框架基线完整性

实体框架基线完整性
EN

Stack Overflow用户
提问于 2017-02-17 13:40:51
回答 1查看 81关注 0票数 0

我首先使用实体框架数据库,我有一个使用基线ids存储历史值的表。我们使用基线id在此表中存储父/子链接。以下列构成此设计:-

  • Id int (主键-唯一)
  • BaselineId int (不是唯一的,但唯一地对同一项进行标识修订)
  • ParentBaselineId int可空(指链接实体的基线,无FK)
  • 最新bit (表示这是系列中的最新基线)

示例数据以提高清晰度

代码语言:javascript
运行
复制
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之前没有完成。

  • 该方法可以同时添加许多必须通过基准ids链接在一起的项。
  • 这必须是单个SQL事务,这样才能在错误时完全回滚。
  • 不能使用SQL触发器来设置基线,因为它们是预先需要的,以指示关系。

我可以采取什么措施来确保同时运行该方法的两个用户不会使用相同的基线?

我的C#看起来像这样

代码语言:javascript
运行
复制
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();
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-02-20 08:51:32

使用@Steve的建议,我能够使用SQL序列。在我的数据库中创建了一个新序列并设置了与现有数据匹配的开始值之后,我将代码更新如下。

代码语言:javascript
运行
复制
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();
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42299458

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档