在SQL Server数据库中以原子方式添加对象及其关系

时间:2013-06-07 12:26:50

标签: sql-server database entity-framework-4 data-integrity

假设我想在我的SQL Server数据库中使用Entity framework 4.0插入新的Experiment

  • Experiment中有1 .. * Tasks
  • ExperimentTask都来自EntityObject
  • 此外,还有一个数据库约束,每个Task必须只有一个“父”Experiment链接到它

插入必须是原子的。我所说的原子是数据库上的读者必须永远不能读取未完全写入数据库的Experiment,例如Experiment没有Task

到目前为止,我尝试过的所有解决方案都存在一些问题,即即使只持续几秒钟,也可以阅读一些不完整的实验。即实验最终会快速填充其任务但不是原子。

更具体地说,

  • 我的reader.exe读入while(true)循环所有实验并转储没有任务的实验。
  • writer.exe并行编写~1000个实验,一个接一个地完成一项任务,然后将它们保存到数据库中。

我无法找到编写ReadAllExperimentsWriteOneExperiment函数的方法,因此我从未阅读过不完整的实验。

我该怎么做?

PS:

我是数据库的新手;我在写入时尝试了可序列化隔离级别的事务,使用UPDLOCK读取了手动SQL请求,但是没有成功解决这个问题,所以我陷入困境。

我认为这是一个非常基本和简单的需求可能会显示出不适合的问题?

问题在这里进行了单元测试: Entity Framework Code First: SaveChanges is not atomic

2 个答案:

答案 0 :(得分:1)

假设您使用READ UNCOMMITTED或类似的隔离级别读取后,以下内容应该实际执行您的目标

using(var ctx = new MyContext())
{
    var task = new Task{};
    ctx.Tasks.Add(task);
    ctx.Experiment.Add(new Experiment{ Task = task });
    ctx.SaveChanges();
}

如果你在这种情况下使用READ UNCOMMITTED或类似的任务,那么在添加实验之前就会显示任务,我不相信在给出你所描述的约束的任务之前,应该存在实验可以存在的状态

答案 1 :(得分:1)

2个解决方案显然解决了我们的问题。

  1. 数据库选项“Is Read Commited Snapshot On”= True(默认情况下,它为false)
  2. 数据库选项“允许快照隔离”= True +使用快照隔离级别完成读取。我们之前尝试使用快照隔离读取,但是不知道这个db选项。我仍然不明白为什么我们在使用禁用隔离级别读取时不会出错?
  3. 有关http://www.codinghorror.com/blog/2008/08/deadlocked.html的更多信息 或者

    MSDN:http://msdn.microsoft.com/en-us/library/ms173763.aspx(搜索READ_COMMITTED_SNAPSHOT)

    http://msdn.microsoft.com/en-us/library/ms179599%28v=sql.105%29.aspx