SaveChanges()没有回滚尝试的事务
本文关键字:事务 SaveChanges | 更新日期: 2023-09-27 18:09:36
我有以下代码(EntityContext。当前是一个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
。我很茫然。这是预期行为吗?我怎样才能防止这种情况发生呢?
这是预期的行为。SaveChanges
尝试在单个数据库事务中提交所有更改。如果失败,则回滚数据库事务,并且不会向数据库写入任何内容。
但是失败的事务不会改变上下文中实体的状态。这就是为什么你的Setting
实体仍然处于Added
状态。
将Error
实体附加到相同的上下文中是一个问题,因为您通常无法将其存储到数据库中,就像本例中一样。我会考虑总是在一个新的上下文中使用专用方法编写错误日志,该方法只打开一个新的上下文中,将Error
实体添加到该上下文中并保存更改。然后立即处理。