Potrzebuję sposobu na rozróżnienie wyjątków SQL za pomocą obiektu LINQ podmiotu, na przykład, jak odróżnić naruszenie ograniczenia dotyczącego ograniczenia klucza lub wyjątkowego naruszenia ograniczenia, gdy wszystko, co otrzymam z wyjątku DbUpdateException, jest toną zagnieżdżonego wyjątki i bezużyteczne długie komunikaty o błędach? Czy są jakieś wyjątki niższego poziomu, gdzie mogę zrobić coś w stylu "Catch FKException"; złap "uniqueException" lub coś w tym stylu.Obsługa wyjątków w strukturze encji 4
Odpowiedz
pomocą SQL kody błędów ...
catch (DbUpdateException ex)
{
var sqlex = ex.InnerException.InnerException as SqlException;
if (sqlex != null)
{
switch (sqlex.Number)
{
case 547: throw new ExNoExisteUsuario("No existe usuario destino."); //FK exception
case 2627:
case 2601:
throw new ExYaExisteConexion("Ya existe la conexion."); //primary key exception
default: throw sqlex; //otra excepcion que no controlo.
}
}
throw ex;
}
try
{
//code
}
catch (System.Data.Entity.Validation.DbEntityValidationException e)
{
string rs = "";
foreach (var eve in e.EntityValidationErrors)
{
rs = string.Format("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:", eve.Entry.Entity.GetType().Name, eve.Entry.State);
Console.WriteLine(rs);
foreach (var ve in eve.ValidationErrors)
{
rs += "<br />" + string.Format("- Property: \"{0}\", Error: \"{1}\"", ve.PropertyName, ve.ErrorMessage);
}
}
throw new Exception(rs);
}
Jeśli chcesz być naprawdę miły, ostatnią linią powinno być 'throw new Exception (rs, e)', aby następna osoba w łańcuchu mogła sprawdzić wewnętrzny wyjątek i zobaczyć stos stacktrace i cokolwiek innego. (Również wyrzucanie niestandardowego wyjątku zamiast ogólnego "Wyjątku" byłoby również miłe) –
Ale naprawdę muszę je rozróżnić, muszę wyrzucać różne wyjątki w zależności od rodzaju błędu bazy danych. – user1777914
pisałem kilka metod narzędziowych do tego:
public static class DbUtils
{
/// <summary>
/// Takes a code block that updates database, runs it and catches db exceptions. If the caught
/// exception is one of those that are ok to ignore (okToIgnoreChecks) then no
/// exception is raised and result is returned. Otherwise an exception is rethrown.
///
/// This function is intended to be run within an explicit transaction, i.e.:
/// using (var transaction = db.Database.BeginTransaction()), which should be committed/rolledback afterwards.
/// Otherwise, if you don't use a transaction discard the db context or in other words make this operation
/// the only one that you run within implicit transaction.
///
/// This function can wrap a single DB statement, but it's more efficient to wrap multiple statements
/// so that locks are held for shorter period of time.
/// If an exception occurs within a transaction and is caught by this function, all other changes
/// will be still saved to DB on commit if transaction is used.
/// </summary>
/// <typeparam name="T">Any result returned by the code block</typeparam>
/// <param name="context">Database connection</param>
/// <param name="dbCodeBlock">
/// Code block to execute that updates DB. It's expected, but not critical that
/// this code does not throw any other exceptions. Do not call SaveChanges() from the code block itself. Let this
/// function do it for you.
/// </param>
/// <param name="okToIgnoreChecks">
/// List of functions that will check if an exception can be ignored.
/// </param>
/// <returns>Returns number of rows affected in DB and result produced by the code block</returns>
public static Tuple<int, T> IgnoreErrors<T>(DbContext context,
Func<T> dbCodeBlock, params Func<DbUpdateException, bool>[] okToIgnoreChecks)
{
var result = dbCodeBlock();
try
{
var rowsAffected = context.SaveChanges();
return Tuple.Create(rowsAffected, result);
}
catch (DbUpdateException e)
{
if (okToIgnoreChecks.Any(check => check(e)))
return Tuple.Create(0, result);
throw;
}
}
public static bool IsDuplicateInsertError(DbUpdateException e)
{
return GetErrorCode(e) == 2601;
}
public static bool IsForeignKeyError(DbUpdateException e)
{
return GetErrorCode(e) == 547;
}
public static T UpdateEntity<T>(DbContext context, T entity, Action<T> entityModifications)
where T : class
{
return EntityCrud(context, entity, (db, e) =>
{
db.Attach(e);
entityModifications(e);
return e;
});
}
public static T DeleteEntity<T>(DbContext context, T entity)
where T : class
{
return EntityCrud(context, entity, (db, e) => db.Remove(e));
}
public static T InsertEntity<T>(DbContext context, T entity)
where T : class
{
return EntityCrud(context, entity, (db, e) => db.Add(e));
}
public static T EntityCrud<T>(DbContext context, T entity, Func<DbSet<T>, T, T> crudAction)
where T : class
{
return crudAction(context.Set<T>(), entity);
}
}
Oto jak można go używać. Przykład wstawienia potencjalnie zduplikowanego wiersza:
DbUtils.IgnoreErrors(_db,() => DbUtils.InsertEntity(_db, someEntity),
DbUtils.IsDuplicateInsertError);
Żaden wyjątek nie zostanie zgłoszony.
Podobny do poprzedniego przykładu, ale obsłużyć FK naruszenie wyjątkiem wyraźnie:
try
{
var numInserted = DbUtils.IgnoreErrors(_db,() => DbUtils.InsertEntity(_db, someEntity), DbUtils.IsDuplicateInsertError).Item1;
// no FK exception, but maybe unique index violation, safe
// to keep going with transaction
}
catch (DbUpdateException e)
{
if (DbUtils.IsForeignKeyError(e))
{
// you know what to do
}
throw; // rethrow other db errors
}
Ostatecznie można nazwać popełnienia transakcję, jeśli masz wyraźne transakcji, poza Zapisz został nazwany już od kontekstu.
- 1. Obsługa błędów bazy danych w strukturze encji
- 2. ASP.NET MVC 4 - Obsługa wyjątków nie działa
- 3. Uruchamianie sql w strukturze encji?
- 4. Obsługa wyjątków w Linuksie
- 5. Obsługa wyjątków w wątkach
- 6. Camel - Obsługa wyjątków w
- 7. Obsługa wyjątków w R
- 8. Dodanie warunku do encji w strukturze podmiotu
- 9. Obsługa wyjątków w kontrolerach Grails
- 10. Utylizacja kontekstu obiektu w strukturze jednostki 4
- 11. Obsługa wyjątków w rozszerzeniach Chrome
- 12. Obsługa wyjątków w Obj-C
- 13. Obsługa wyjątków API w RxJava
- 14. Obsługa wyjątków globalnych w VB
- 15. Obsługa wyjątków ObjC w monotouch
- 16. Obsługa wyjątków w rdzeniu asp.net?
- 17. Obsługa wyjątków zmiennoprzecinkowych w C++
- 18. Obsługa wyjątków pracowników tła
- 19. Obsługa wyjątków węzła
- 20. Obsługa wyjątków NHibernate
- 21. NSFileHandle writeData: obsługa wyjątków
- 22. Obsługa wyjątków ASP.NET MVC
- 23. Obsługa wyjątków Spring Resttemplate
- 24. EJB 3.0 Obsługa wyjątków
- 25. Obsługa wyjątków Python
- 26. Obsługa wyjątków Wcf
- 27. Obsługa wyjątków przez Reactor Wiosna
- 28. Haskell: obsługa wyjątków w monadach bez IO
- 29. Obsługa wyjątków dla wielu tras
- 30. Obsługa błędów STL bez wyjątków
Często wewnętrzne wyjątki będą zawierać numeryczne kody błędów, czy próbowałeś je sprawdzić? Opublikuj przykład wyjątku w swoim pytaniu, podkreśl tekst i kliknij przycisk '{}, aby go ładnie sformatować. –