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

Nat*_*per 4 c# sql sql-server entity-framework azure

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

在我的代码中,Messages属于Conversations.收到消息后,我将其添加到Messages表并在Conversations表中创建其父级.如果我同时使用同一个父进行两条消息,则可能会将具有相同主键的值双重插入到Conversations表中.

过程:

如果它不存在代码,我会调用一些"插入对话":

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

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


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

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

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

Col*_*lin 6

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

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); 
}
Run Code Online (Sandbox Code Playgroud)

参考:

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


小智 5

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

您在这里是一个人 - 甚至询问开发人员都没有意义,因为他们正忙于 EF 7,甚至暂时放弃功能以实现这一目标(例如继承)。也许在一两年内,一旦 EF 具有更多功能并且在 v7 中稳定……但不,目前没有。

您必须在自己的应用程序逻辑中解决这个问题。