Joh*_*lds 41 .net c# entity-framework
在调用时DbContext.SaveChanges,我得到一个DbUpdateException:
EntityFramework.dll中发生了未处理的"System.Data.Entity.Infrastructure.DbUpdateException"类型异常.附加信息:更新条目时发生错误.有关详细信息,请参阅内部异常
不幸的是,没有内在的例外(至少,不是我能看到的).有没有办法确切地知道为什么SaveChanges抛出异常?至少,看看SaveChanges在发生错误时尝试更新的表格会很有帮助.
Col*_*lin 28
这是我对SaveChanges的重写.它给了我一个放置断点的有用位置:
public override int SaveChanges()
{
try
{
return base.SaveChanges();
}
catch (DbEntityValidationException e)
{
foreach (var eve in e.EntityValidationErrors)
{
Debug.WriteLine(@"Entity of type ""{0}"" in state ""{1}""
has the following validation errors:",
eve.Entry.Entity.GetType().Name,
eve.Entry.State);
foreach (var ve in eve.ValidationErrors)
{
Debug.WriteLine(@"- Property: ""{0}"", Error: ""{1}""",
ve.PropertyName, ve.ErrorMessage);
}
}
throw;
}
catch(DbUpdateException e)
{
//Add your code to inspect the inner exception and/or
//e.Entries here.
//Or just use the debugger.
//Added this catch (after the comments below) to make it more obvious
//how this code might help this specific problem
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
throw;
}
}
Run Code Online (Sandbox Code Playgroud)
参考:
一个或多个实体的验证失败.有关详细信息,请参阅"EntityValidationErrors"属性
a-h*_*a-h 16
这是我对SaveChanges的重写,显示了处理DbUpdateException的其他代码(根据问题).
public override int SaveChanges()
{
try
{
return base.SaveChanges();
}
catch (DbEntityValidationException vex)
{
var exception = HandleDbEntityValidationException(vex);
throw exception;
}
catch(DbUpdateException dbu)
{
var exception = HandleDbUpdateException(dbu);
throw exception;
}
}
private Exception HandleDbUpdateException(DbUpdateException dbu)
{
var builder = new StringBuilder("A DbUpdateException was caught while saving changes. ");
try
{
foreach (var result in dbu.Entries)
{
builder.AppendFormat("Type: {0} was part of the problem. ", result.Entity.GetType().Name);
}
}
catch (Exception e)
{
builder.Append("Error parsing DbUpdateException: " + e.ToString());
}
string message = builder.ToString();
return new Exception(message, dbu);
}
Run Code Online (Sandbox Code Playgroud)
我没有使日志代码非常具体,但它改进了类似的标准错误消息:
The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value.
Run Code Online (Sandbox Code Playgroud)
这样,至少我可以看到哪个实体有问题,而这通常足以解决问题.
根据Colin的回答,可以提供有关EF持久性故障的完整详细信息,如下所示:
public bool SaveChangesEx()
{
try
{
SaveChanges();
return true;
}
catch (DbEntityValidationException exc)
{
// just to ease debugging
foreach (var error in exc.EntityValidationErrors)
{
foreach (var errorMsg in error.ValidationErrors)
{
// logging service based on NLog
Logger.Log(LogLevel.Error, $"Error trying to save EF changes - {errorMsg.ErrorMessage}");
}
}
throw;
}
catch (DbUpdateException e)
{
var sb = new StringBuilder();
sb.AppendLine($"DbUpdateException error details - {e?.InnerException?.InnerException?.Message}");
foreach (var eve in e.Entries)
{
sb.AppendLine($"Entity of type {eve.Entity.GetType().Name} in state {eve.State} could not be updated");
}
Logger.Log(LogLevel.Error, e, sb.ToString());
throw;
}
}
Run Code Online (Sandbox Code Playgroud)
除了验证错误,更新异常将输出一般错误和上下文信息.
注意:此代码需要C#6.0才能工作,因为它使用空传播和字符串插值.
对于.NET Core,代码稍有更改,因为可能引发的异常具有不同的结构/填充不同:
public void SaveChangesEx()
{
try
{
// this triggers defined validations such as required
Context.Validate();
// actual save of changes
Context.SaveChangesInner();
}
catch (ValidationException exc)
{
Logger.LogError(exc, $"{nameof(SaveChanges)} validation exception: {exc?.Message}");
throw;
}
catch (DbUpdateException exc)
{
Logger.LogError(exc, $"{nameof(SaveChanges)} db update error: {exc?.InnerException?.Message}");
throw;
}
catch (Exception exc)
{
// should never reach here. If it does, handle the more specific exception
Logger.LogError(exc, $"{nameof(SaveChanges)} generic error: {exc.Message}");
throw;
}
}
Run Code Online (Sandbox Code Playgroud)
如果不立即处理相同的上下文,则可以增强上下文以自动拒绝失败时的更改:
public void RejectChanges()
{
foreach (var entry in ChangeTracker.Entries().Where(e => e.Entity != null).ToList())
{
switch (entry.State)
{
case EntityState.Modified:
case EntityState.Deleted:
entry.State = EntityState.Modified; //Revert changes made to deleted entity.
entry.State = EntityState.Unchanged;
break;
case EntityState.Added:
entry.State = EntityState.Detached;
break;
}
}
}
public bool SaveChangesInner()
{
try
{
SaveChanges();
return true;
}
catch (Exception)
{
RejectChanges();
throw;
}
}
Run Code Online (Sandbox Code Playgroud)
当真正的异常似乎在某处丢失时,最好的办法是打破每个异常。无论它是在某个地方被抓住还是被吞下,在你够不着的地方,调试器都会崩溃,让你看看发生了什么。
有关更多信息,请参阅此 MSDN 链接:
| 归档时间: |
|
| 查看次数: |
73727 次 |
| 最近记录: |