【问题标题】:A SQL 2005 Database Design and Entity Framework transaction conundrumSQL 2005 数据库设计和实体框架事务难题
【发布时间】:2009-12-16 11:46:24
【问题描述】:

我有一个数据库设计问题,我正在尝试将其纳入实体框架。它的复杂,我继承了它,并且已经来不及做出大的改变!在决定如何前进之前,我想借鉴其他人的智慧……我原来的帖子要长得多,但我认为业务逻辑细节可能并不重要。

所以简单地说明问题,假设我在同一个数据库中有两个表:

表A

身份证, (其他列...)

表B

身份证, TableId (

现在 TableB 对表 A 有一个“软键”,通常可以是外键,但对于我拥有的架构,它不是,相信我不可能(原因是“假外键key” 指向 76 个不同表中的任何一个,具体取决于 TableB 的“TableTypeId”列中的内容)。

现在,我们正在使用实体框架。显然,两个表之间不能有导航属性。问题是我需要在一个事务中处理这两个表。例如,当我向 TableA 中添加一条记录时,我还需要向 TableB 中添加一条记录,并将 TableA 中创建的新 Identity 值用于 TableB 的“TableId”列。

使用导航属性,我可以连接内存中的两个 EntityObject,然后调用 Context.SaveChanges() 和 EntityFramework 在事务中完成这一切。但是,如果没有导航属性,我必须先插入 TableA,获取标识,然后使用第一次插入的结果插入 TableB。这是两笔交易...

我听说实体框架允许您在更复杂的情况下使用事务做更多的事情,例如定义自己的事务范围和使用 COntext.SaveChanges() 的其他参数。但是,在我尝试这个之前,我想知道我的问题是否可以在单个事务中解决......

除了架构重新设计之外,我还有什么选择...

谢谢

【问题讨论】:

    标签: entity-framework schema


    【解决方案1】:

    哎哟……

    在 EF 4.0 中,您可以覆盖保存更改方法,手动启动事务,将 TableB 模型设置为未更改,保存表 A,AcceptAllChanges(),将 TableB 标记为已更改,然后保存 TableB。

    对于 EF1,您必须手动启动环境事务(使用 var scope = new TransactionScope){},然后执行相同的过程。将 TableA 添加到您的上下文中,如果已经添加标记 TableB 为未更改,请调用 SaveChanges(希望只保存您的 TableA 对象),调用 AcceptAllChanges(),将 TableB 更新为已更改并添加您的软键值,再次调用 SaveChanges。完成交易。

    AcceptAllChanges() 或 ChangeObjectState() 是你的朋友:

    http://msdn.microsoft.com/en-us/library/system.data.objects.objectstatemanager.changeobjectstate(VS.100).aspx

    http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext.acceptallchanges(VS.100).aspx

    在这两种情况下都必须告诉 EF 忽略 TableB,保存 TableA,然后在环境事务中再次关心 TableB。这是 100% 可能的(我会做类似的事情)它只是需要一些工作。

    伪代码:

      using (TransactionScope transaction = new TransactionScope())
      {
            //Set TableB as unchanged so EF ignores it
          YourObjectContext.ObjectStateManager.ChangeObjectState(TableBObject,EntityState.Unchanged);
    
          YourObjectContext.SaveChanges();
          YourObjectContext.AcceptAllChanges();
    
          TableB.SoftFK = TableA.Fk;          
    
          YourObjectContext.ObjectStateManager.ChangeObjectState(TableBObject,EntityState.Modified);
    
          YourObjectContext.SaveChanges();
          YourObjectContext.AcceptAllChanges();
    
          Transaction.Complete();
      }
    

    【讨论】:

      猜你喜欢
      • 2016-05-21
      • 1970-01-01
      • 2011-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-14
      • 1970-01-01
      • 2020-11-16
      相关资源
      最近更新 更多