我有以下代码(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);
}


我期望(根据this answer)是当未完成的更改失败时将回滚它们。但是,在我的错误日志记录方法中,我看到它们尚未出现。

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()包装在事务中,但是发生了相同的问题。

按照this answer,我的连接字符串也不包含Enlist=false。我很茫然。这是预期的行为吗?以及如何防止这种情况发生?

最佳答案

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

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

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

关于c# - Entity Framework 5 SaveChanges()不回滚尝试的事务,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16068505/

10-10 17:33
查看更多