我有以下代码(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
。我不知所措。这是预期的行为吗?我怎样才能防止这种情况发生?
答案 0 :(得分:3)
这是预期的行为。 SaveChanges
尝试在单个数据库事务中提交所有更改。如果失败,则回滚数据库事务,并且不会将任何内容写入数据库。
但失败的交易不会改变上下文中实体的状态。这就是您的Setting
实体仍处于州Added
状态的原因。
将Error
实体附加到同一上下文是一个问题,因为您经常无法将其存储到数据库中,就像在此示例中一样。我会考虑始终在新的上下文中使用专用方法编写错误日志,该方法仅打开新上下文,将Error
实体添加到此上下文并保存更改。然后立即处理它。