Did you know that exceptions thrown by Entity Framework contain useful information? They are buried in some properties of an inner exception. Here's the code that makes them visible:
public static class Extensions
{
public static string Render(this Exception ex, bool noTrace = false)
{
var s = new StringBuilder("\n");
int i = 0;
do
{
s.AppendFormat("{0:#\\. inner E;;E}xception ({1}):\n {2}\n",
i++,
ex.GetType().Name,
ex.Message.Replace("\n", "\n "));
if (ex is UpdateException)
{
foreach (var stateEntry in ((UpdateException)ex).StateEntries)
{
var entity = stateEntry.Entity ?? new object();
s.AppendFormat(" {0} {1}: {2}\n", stateEntry.State, entity.GetType().Name, entity);
var values =
stateEntry.State == EntityState.Deleted
? stateEntry.OriginalValues
: stateEntry.CurrentValues;
for (int j = 0; j < values.FieldCount; j++)
{
var currentValue = values[j];
var originalValue =
stateEntry.State == EntityState.Added
? currentValue
: stateEntry.OriginalValues[j];
s.AppendFormat(originalValue.Equals(currentValue) ? " {0}: <{1}>\n" : " {0}: <{1}>→<{2}\n",
values.GetName(j), originalValue, currentValue);
}
}
}
s.AppendFormat(noTrace ? "\n" : "Trace:\n{0}\n", ex.StackTrace);
ex = ex.InnerException;
}
while (ex != null);
return s.ToString();
}
}