Entity Framework SaveChanges error details

后端 未结 5 1291
攒了一身酷
攒了一身酷 2021-02-18 14:35

When saving changes with SaveChanges on a data context is there a way to determine which Entity causes an error? For example, sometimes I\'ll forget to assign a da

相关标签:
5条回答
  • 2021-02-18 14:49

    If all you need to do is see the actual inner exception instead, all you have to do is put the save changes inside of a try block, catch the exception and look at it.

    I do it all the time and it works perfectly.

    0 讨论(0)
  • 2021-02-18 14:55

    I think I might make separate calls to SaveChanges(). That is usually what I do for exactly this reason. Can I ask why you are saving multiple entities at a time? If you have to, I would follow the other guy's advice and validate the entities beforehand.

    Or maybe there is a better way to structure your code so that in valid entiies won't even be attempted to be saved. Maybe detach your entities, and then run them through a validation method before attaching them to the new context. Hope that helps!

    0 讨论(0)
  • 2021-02-18 14:58

    I think it is not possible: you could play with the states of the objects for knowing which will be saved (before saving) and which has been saved (in the exception), but in the second set you will not be able to know which one throwed the exception.

    Spanish version : http://msdn.microsoft.com/es-es/library/cc716714.aspx

    English : http://msdn.microsoft.com/en-us/library/cc716714.aspx

    0 讨论(0)
  • 2021-02-18 15:11

    One option is to handle the ObjectContext.SavingChanges Event, which gives you a chance to perform validation on entities before the changes are saved and even cancel the save if necessary. This way you can make sure any non-nullable properties are set before trying to save changes, and avoid having to rely on exception handling.

    0 讨论(0)
  • 2021-02-18 15:11

    Here is my sample of couple checkers: either datetime = 0 or string overflows:

    
    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;
                }
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题