3

我有以下代码(EntityContext.Current 是一个 DbContext):

try {
    Setting s = new Setting
    {
        id = 1,
        user_id = 0
    };

    EntityContext.Current.Settings.Add(s);
    EntityContext.Current.SaveChanges(); //this violates a foreign key constraint and therefore throws an exception
} catch (Exception ex) {
    ErrorContext.Log(ex);
}

我期望(根据这个答案)是挂起的更改在失败时将被回滚。但是,在我的错误记录方法中,我发现它们没有。

Error e = new Error
{
    message = ex.Message
};

EntityContext.Current.Errors.Add(e);

var pending = ((IObjectContextAdapter)EntityContext.Current).ObjectContext.ObjectStateManager.GetObjectStateEntries(System.Data.EntityState.Added);
//this contains both my new error entity and my old setting entity which shouldn't be here

EntityContext.Current.SaveChanges();

当我的应用程序尝试在数据库中记录错误时,它还尝试(再次)使用无效的外键约束保存设置,这会导致添加错误日志记录失败。

这是我第一次使用 EF 遇到这种行为。我尝试将第一个包装SaveChanges()在事务中,但发生了同样的问题。

根据这个答案,我的连接字符串也不包含Enlist=false。我不知所措。这是预期的行为吗?我怎样才能防止这种情况发生?

4

1 回答 1

3

这是预期的行为。SaveChanges尝试在单个数据库事务中提交所有更改。如果失败,数据库事务将回滚,并且不会向数据库写入任何内容。

但是失败的事务不会改变上下文中实体的状态。这就是您的Setting实体仍处于 state的原因Added

将您的实体附加Error到相同的上下文是一个问题,因为您通常无法将其存储到数据库中,就像在这个示例中一样。我会考虑使用仅打开新上下文、将Error实体添加到此上下文并保存更改的专用方法始终在新上下文中写入错误日志。然后立即丢弃。

于 2013-04-17T21:44:46.007 回答