vea varias validaciĆ³n una solucion propiedad para framework exceptions errors error entityvalidationerrors entidades dbentityvalidationexception data c# entity-framework

c# - varias - system data entity validation dbentityvalidationexception



Detalles de error de Entity Framework SaveChanges (5)

Aquí está mi ejemplo de comprobadores de parejas: datetime = 0 o desbordamientos de cadenas:

public partial class MyContext { private static Dictionary> _fieldMaxLengths; partial void OnContextCreated() { InitializeFieldMaxLength(); SavingChanges -= BeforeSave; SavingChanges += BeforeSave; } private void BeforeSave(object sender, EventArgs e) { StringOverflowCheck(sender); DateTimeZeroCheck(sender); CheckZeroPrimaryKey(sender); } private static void CheckZeroPrimaryKey(object sender) { var db = (CTAdminEntities)sender; var modified = db.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified); foreach (var entry in modified.Where(entry => !entry.IsRelationship)) { var entity = (EntityObject)entry.Entity; Debug.Assert(entity != null); var type = entity.GetType(); foreach (var prop in type.GetProperties().Where( p => new[] { typeof(Int64), typeof(Int32), typeof(Int16) }.Contains(p.PropertyType))) { var attr = prop.GetCustomAttributes(typeof (EdmScalarPropertyAttribute), false); if (attr.Length > 0 && ((EdmScalarPropertyAttribute) attr[0]).EntityKeyProperty) { long value = 0; if (prop.PropertyType == typeof(Int64)) value = (long) prop.GetValue(entity, null); if (prop.PropertyType == typeof(Int32)) value = (int) prop.GetValue(entity, null); if (prop.PropertyType == typeof(Int16)) value = (short) prop.GetValue(entity, null); if (value == 0) throw new Exception(string.Format("PK is 0 for Table {0} Key {1}", type, prop.Name)); break; } } } } private static void DateTimeZeroCheck(object sender) { var db = (CTAdminEntities)sender; var modified = db.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified); foreach (var entry in modified.Where(entry => !entry.IsRelationship)) { var entity = (EntityObject)entry.Entity; Debug.Assert(entity != null); var type = entity.GetType(); foreach (var prop in type.GetProperties().Where(p => p.PropertyType == typeof(DateTime))) { var value = (DateTime)prop.GetValue(entity, null); if (value == DateTime.MinValue) throw new Exception(string.Format("Datetime2 is 0 Table {0} Column {1}", type, prop.Name)); } foreach (var prop in type.GetProperties().Where( p => p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(Nullable) && p.PropertyType.GetGenericArguments()[0] == typeof(DateTime))) { var value = (DateTime?)prop.GetValue(entity, null); if (value == DateTime.MinValue) throw new Exception(string.Format("Datetime2 is 0 Table {0} Column {1}", type, prop.Name)); } } } private static void StringOverflowCheck(object sender) { var db = (CTAdminEntities)sender; var modified = db.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified); foreach (var entry in modified.Where(entry => !entry.IsRelationship)) { var entity = (EntityObject)entry.Entity; Debug.Assert(entity != null); var type = entity.GetType(); var fieldMap = _fieldMaxLengths[type.Name]; foreach (var key in fieldMap.Keys) { var value = (string)type.GetProperty(key).GetValue(entity, null); if (value != null && value.Length > fieldMap[key]) throw new Exception(string.Format("String Overflow on Table {0} Column {1}: {2} out of {3}", type, key, value.Length, fieldMap[key])); } } } private void InitializeFieldMaxLength() { if (_fieldMaxLengths != null) return; _fieldMaxLengths = new Dictionary>(); var items = MetadataWorkspace.GetItems(DataSpace.CSpace); Debug.Assert(items != null); var tables = items.Where(m => m.BuiltInTypeKind == BuiltInTypeKind.EntityType); foreach (EntityType table in tables) { var fieldsMap = new Dictionary(); _fieldMaxLengths[table.Name] = fieldsMap; var stringFields = table.Properties.Where(p => p.DeclaringType.Name == table.Name && p.TypeUsage.EdmType.Name == "String"); foreach (var field in stringFields) { var value = field.TypeUsage.Facets["MaxLength"].Value; if (value is Int32) fieldsMap[field.Name] = Convert.ToInt32(value); else // unbounded fieldsMap[field.Name] = Int32.MaxValue; } } } }

Cuando se guardan cambios con SaveChanges en un contexto de datos, ¿hay una manera de determinar qué Entidad causa un error? Por ejemplo, a veces me olvido de asignar una fecha a un campo de fecha no anulable y obtengo el error "Intervalo de fecha no válido", pero no obtengo información sobre qué entidad o qué campo es causada por (generalmente puedo rastrearlo) Pasando con esmero por todos mis objetos, pero consume mucho tiempo). El seguimiento de la pila es bastante inútil ya que solo me muestra un error en la llamada a SaveChanges sin ninguna información adicional sobre dónde ocurrió exactamente.

Tenga en cuenta que no estoy buscando resolver ningún problema en particular que tengo ahora, solo me gustaría saber en general si hay una manera de saber qué entidad / campo está causando un problema.

Ejemplo rápido de un seguimiento de la pila como ejemplo: en este caso, se produjo un error porque la fecha de CreatedOn no se estableció en la entidad IAComment , sin embargo, es imposible distinguirlo de este error / seguimiento de la pila

[SqlTypeException: SqlDateTime overflow. Must be between 1/1/1753 12:00:00 AM and 12/31/9999 11:59:59 PM.] System.Data.SqlTypes.SqlDateTime.FromTimeSpan(TimeSpan value) +2127345 System.Data.SqlTypes.SqlDateTime.FromDateTime(DateTime value) +232 System.Data.SqlClient.MetaType.FromDateTime(DateTime dateTime, Byte cb) +46 System.Data.SqlClient.TdsParser.WriteValue(Object value, MetaType type, Byte scale, Int32 actualLength, Int32 encodingByteSize, Int32 offset, TdsParserStateObject stateObj) +4997789 System.Data.SqlClient.TdsParser.TdsExecuteRPC(_SqlRPC[] rpcArray, Int32 timeout, Boolean inSchema, SqlNotificationRequest notificationRequest, TdsParserStateObject stateObj, Boolean isCommandProc) +6248 System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) +987 System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) +162 System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) +32 System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) +141 System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) +12 System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior) +10 System.Data.Mapping.Update.Internal.DynamicUpdateCommand.Execute(UpdateTranslator translator, EntityConnection connection, Dictionary`2 identifierValues, List`1 generatedValues) +8084396 System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, IEntityAdapter adapter) +267 [UpdateException: An error occurred while updating the entries. See the inner exception for details.] System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, IEntityAdapter adapter) +389 System.Data.EntityClient.EntityAdapter.Update(IEntityStateManager entityCache) +163 System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options) +609 IADAL.IAController.Save(IAHeader head) in C:/Projects/IA/IADAL/IAController.cs:61 IA.IAForm.saveForm(Boolean validate) in C:/Projects/IA/IA/IAForm.aspx.cs:198 IA.IAForm.advance_Click(Object sender, EventArgs e) in C:/Projects/IA/IA/IAForm.aspx.cs:287 System.Web.UI.WebControls.Button.OnClick(EventArgs e) +118 System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +112 System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +10 System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +13 System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +36 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +5019



Creo que podría hacer llamadas separadas a SaveChanges (). Eso suele ser lo que hago exactamente por esta razón. ¿Puedo preguntar por qué está guardando varias entidades a la vez? Si es necesario, seguiré los consejos del otro chico y validaré las entidades de antemano.

O tal vez haya una mejor manera de estructurar su código para que, en entidades válidas, ni siquiera se intente guardar. Tal vez separe sus entidades y luego ejecútelas a través de un método de validación antes de adjuntarlas al nuevo contexto. ¡Espero que ayude!


Si todo lo que necesita hacer es ver la excepción interna real en su lugar, todo lo que tiene que hacer es colocar los cambios guardados dentro de un bloque try, capturar la excepción y mirarla.

Lo hago todo el tiempo y funciona perfectamente.


Una opción es manejar el evento ObjectContext.SavingChanges , que le brinda la oportunidad de realizar una validación en las entidades antes de que se guarden los cambios e incluso cancelar el guardado si es necesario. De esta manera, puede asegurarse de que todas las propiedades no anulables estén establecidas antes de intentar guardar los cambios y evitar tener que depender del manejo de excepciones.