重试实体框架 DbContext.SaveChanges 后双重插入密钥



我在Azure上使用Entity Framework。对我的数据进行一些更改后,我调用DbContext.SaveChanges

在我的代码中,Messages属于Conversations。收到消息后,我将其添加到"消息"表中,并在"对话"表中创建其父级。如果我同时收到具有相同父级的两条消息,则有可能将具有相同主键的值双重插入到对话表中。

过程:

我将调用一些"如果不存在代码则插入对话":

 if (this.Context.Conversations.SingleOrDefault(fc => fc.ConversationId == conversation.ConversationId) == null)
        {
            Context.Entry(conversation).State = EntityState.Added; //public DbEntityEntry Entry(object entity);
        }

稍后我会打电话给this.Context.SaveChanges


我一直在阅读SQL Azure和实体框架连接错误处理,我很确定我想实现具有事务范围的重试策略。

  • 如何在重试策略中包装SaveChanges一些想法:如何在重试策略中包装SaveChanges。这会重试我之前运行的检查对话是否存在的代码吗?如何使我的重试策略重试非暂时性故障(如 PK 违规(?

  • 如果重试
  • 策略是不可能的,那么在保存上下文时尽可能低地埋葬"创建或编辑(如果存在("逻辑的实体框架方法是什么?在这种特殊情况下,最好只调用存储过程吗?

这听起来更像是您想要的并发重试模式:

using (var context = new BloggingContext()) 
{ 
    var blog = context.Blogs.Find(1); 
    blog.Name = "The New ADO.NET Blog"; 
    bool saveFailed; 
    do 
    { 
        saveFailed = false; 
        try 
        { 
            context.SaveChanges(); 
        } 
        catch (DbUpdateConcurrencyException ex) 
        { 
            saveFailed = true; 
            // Update the values of the entity that 
            //failed to save from the store 
            ex.Entries.Single().Reload(); 
        } 
    } while (saveFailed); 
}

参考:

http://msdn.microsoft.com/en-gb/data/jj592904.aspx

可悲的是 - 你没有。这不在 EF 可以开箱即用的范围内。重试逻辑显式仅处理暂时性连接问题。并且没有重试逻辑可以神奇地修复 PK 问题。EF 中也没有"更新插入"(更新或插入(逻辑。

你在这里只能靠自己 - 甚至问开发人员都没有意义,因为他们忙于 EF 7,甚至暂时放弃功能来实现这一点(如继承(。也许在一两年内,一旦 EF 具有更多功能并且在 v7 中稳定......但是不,目前什么都没有。

您必须在自己的应用程序逻辑中对此进行整理。

最新更新