首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何处理实体框架上的UpdateException --“违反主键约束”?

如何处理实体框架上的UpdateException --“违反主键约束”?
EN

Stack Overflow用户
提问于 2014-04-08 16:00:52
回答 4查看 5.9K关注 0票数 6

我有一个允许多个用户的应用程序和一个具有两个ID作为复合密钥的数据库表。这些ID也是来自另一个表的外键。因此,当两个用户试图使用相同的ID向该表添加一个条目时,其中一个用户将获得一个UpdateException,因为主键违反了。我已经发现应该这样处理:

代码语言:javascript
复制
try
{
    result = base.SaveChanges(options);
}
catch (UpdateException ex)
{
    SqlException innerException = ex.InnerException as SqlException;
    if (innerException != null && innerException.Number == 2627 || innerException.Number == 2601)
    {
        // handle here
    }
    else
    {
        throw;
    }
}

但是,在“//处理这里”部分,我实际上做了什么。我尝试刷新对象,但它处于“添加”状态,因此无法刷新。我要做的是:承认已经有一个具有这些is的对象,删除它想要插入的对象,并从数据库加载现有的对象。我怎么能这么做?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2016-01-25 09:54:51

自从我投了一票,我回头看了一下我是如何解决这个问题的。我就是这样做的:

代码语言:javascript
复制
// Exception number 2627 = Violation of %ls constraint '%.*ls'. Cannot insert duplicate key in object '%.*ls'.
// Exception number 2601 = Cannot insert duplicate key row in object '%.*ls' with unique index '%.*ls'.
// See http://msdn.microsoft.com/en-us/library/cc645603.aspx for more information and possible exception numbers
if (innerException != null && (innerException.Number == 2627 || innerException.Number == 2601))
{
    // Resolve the primary key conflict by refreshing and letting the store win
    // In order to be able to refresh the entity its state has to be changed from Added to Unchanged
    ObjectStateEntry ose = ex.StateEntries.Single();
    this.ObjectStateManager.ChangeObjectState(ose.Entity, EntityState.Unchanged);
    base.Refresh(RefreshMode.StoreWins, ose.Entity);

    // Refresh addedChanges now to remove the refreshed entry from it
    addedChanges = this.ObjectStateManager.GetObjectStateEntries(System.Data.EntityState.Added).Where(s => !s.IsRelationship);
}
else
{
    throw;
}

编辑:

请注意,UpdateException已重命名为DbUpdateException,以EF4.1开头。

票数 3
EN

Stack Overflow用户

发布于 2016-04-27 17:11:18

我必须使用以下方法才能让它对我起作用-我使用的是一个异步函数,但是我已经测试过了,而且它没有使用异步.

代码语言:javascript
复制
try
{
    await db.SaveChangesAsync();
}
catch (DbUpdateException ex)
{
    SqlException innerException = ex.InnerException.InnerException as SqlException;
    if (innerException != null && (innerException.Number == 2627 || innerException.Number == 2601))
    {
        //your handling stuff
    }
    else
    {
        throw;
    }
}

我发现如果我不使用DbUpdateException,它就会直接通过捕获,我的ex.InnerException和一个额外的InnerException对象,为了使它变成错误号.

票数 1
EN

Stack Overflow用户

发布于 2014-04-08 22:08:39

因此,当两个用户试图使用相同的ID向该表添加一个条目时,其中一个用户将获得一个UpdateException,因为主键违反了。

正确--如果你有一个主键(不管是1列还是多列),它必须是唯一的。

我要做的是:承认已经有一个具有这些is的对象,删除它想要插入的对象,并从数据库加载现有的对象。

这有点难回答,因为我们不知道这种方法应该返回什么,等等。

  • 在我们建议你方如何“确认”之前,我们必须知道这一点。
  • 放下物体很容易--你不用再用它做任何事情了。
  • 最后,要加载现有对象。这有必要吗?一旦装好了,你打算拿它做什么?假设您希望用传入的值更新现有的对象(我不会,但假设这就是您需要做的)。您所需要做的就是将它从DB读入一个新对象,更新要更改的字段,然后保存它。

以下是一个可能的例子:

代码语言:javascript
复制
var exisitingEntity = context.TheEntity;
existingEntity.Property1 = options.Property1;
existingEntity.Property2 = options.Property2;
...
context.SaveChanges(existingEntity);
return "Object already existed, but was updated with the values passed in."
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22942271

复制
相关文章

相似问题

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