복붙노트

[SQL] 엔티티 프레임 워크를 사용하여 SQL Server 데이터베이스에 대한 변경 사항을 저장하는 동안 검증은 하나 이상의 엔티티 실패

SQL

엔티티 프레임 워크를 사용하여 SQL Server 데이터베이스에 대한 변경 사항을 저장하는 동안 검증은 하나 이상의 엔티티 실패

나는 데이터베이스에 내 편집을 저장할 나는 ASP.NET MVC 3 / C #에서 엔티티 프레임 워크 코드 - 일층를 사용하고 있지만 점점 오류입니다. 내 이벤트 클래스에서 나는 날짜 시간 및 시간 범위 데이터 유형을 가지고 있지만 내 데이터베이스에, 나는 각각 날짜와 시간을 가지고있다. 이 이유가 될 수 있을까요? 어떻게 데이터베이스에 변경 사항을 저장하기 전에 코드에서 적절한 데이터 형식으로 캐스팅 할 수 있습니다.

public class Event
{
    public int EventId { get; set; }
    public int CategoryId { get; set; }
    public int PlaceId { get; set; }
    public string Title { get; set; }
    public decimal Price { get; set; }
    public DateTime EventDate { get; set; }
    public TimeSpan StartTime { get; set; }
    public TimeSpan EndTime { get; set; }
    public string Description { get; set; }
    public string EventPlaceUrl { get; set; }
    public Category Category { get; set; }
    public Place Place { get; set; }
}

storeDB.SaveChanges ()에서 문제 >>>> 컨트롤러 메소드;

// POST: /EventManager/Edit/386        
[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
    var theEvent = storeDB.Events.Find(id);

    if (TryUpdateModel(theEvent))
    {
        storeDB.SaveChanges();
        return RedirectToAction("Index");
    }
    else
    {
        ViewBag.Categories = storeDB.Categories.OrderBy(g => g.Name).ToList();
        ViewBag.Places = storeDB.Places.OrderBy(a => a.Name).ToList();
        return View(theEvent);
    }
}

public class EventCalendarEntities : DbContext
{
    public DbSet<Event> Events { get; set; }
    public DbSet<Category> Categories { get; set; }
    public DbSet<Place> Places { get; set; } 
}

SQL 서버 2008 R2 데이터베이스 / T-SQL

EventDate (Datatype = date)  
StartTime (Datatype = time)  
EndTime (Datatype = time)  

HTTP를 양식

EventDate (Datatype = DateTime) e.g. 4/8/2011 12:00:00 AM  
StartTime (Datatype = Timespan/time not sure) e.g. 08:30:00  
EndTime (Datatype = Timespan/time not sure) e.g. 09:00:00  

'/'응용 프로그램에 서버 오류가 있습니다.

검증은 하나 이상의 개체 실패했습니다. 자세한 내용은 'EntityValidationErrors'속성을 참조하십시오.

설명 : 처리되지 않은 예외가 현재 웹 요청을 실행하는 동안 일어났다. 오류 및 어디 코드에서 유래에 대한 자세한 내용은 스택 추적을 검토하십시오.

예외 정보 : System.Data.Entity.Validation.DbEntityValidationException : 검증은 하나 이상의 개체 실패했습니다. 자세한 내용은 'EntityValidationErrors'속성을 참조하십시오.

소스 오류 :

Line 75:             if (TryUpdateModel(theEvent))
Line 76:             {
Line 77:                 storeDB.SaveChanges();
Line 78:                 return RedirectToAction("Index");
Line 79:             }

소스 파일 : C : \ 9월 \ MvcEventCalendar \ MvcEventCalendar \ 컨트롤러 \ EventManagerController.cs 라인 : 77

스택 추적 :

[DbEntityValidationException : 검증은 하나 이상의 개체 실패했습니다. 자세한 내용은 'EntityValidationErrors'속성을 참조하십시오.]

해결법

  1. ==============================

    1.다음과 같은 코드로 DbEntityValidationException에서 모든 정보를 추출 할 수 있습니다 (: 당신의 사용 목록에 System.Data.Entity.Validation과 System.Diagnostics 네임 당신은 네임 스페이스를 추가해야합니다) :

    다음과 같은 코드로 DbEntityValidationException에서 모든 정보를 추출 할 수 있습니다 (: 당신의 사용 목록에 System.Data.Entity.Validation과 System.Diagnostics 네임 당신은 네임 스페이스를 추가해야합니다) :

    catch (DbEntityValidationException dbEx)
    {
        foreach (var validationErrors in dbEx.EntityValidationErrors)
        {
            foreach (var validationError in validationErrors.ValidationErrors)
            {
                Trace.TraceInformation("Property: {0} Error: {1}", 
                                        validationError.PropertyName, 
                                        validationError.ErrorMessage);
            }
        }
    }
    
  2. ==============================

    2.어떤 코드 변경이 필요하지 않습니다 :

    어떤 코드 변경이 필요하지 않습니다 :

    당신이 잡아 내에서 디버그 모드에있는 동안 {...} 블록은 "간략한"창 (Ctrl + Alt + Q)를 열고 거기에 붙여 넣기 :

    ((System.Data.Entity.Validation.DbEntityValidationException)ex).EntityValidationErrors
    

    또는:

    ((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors
    

    당신이 시도 / 캐치하지 않거나 할 경우 예외 객체에 액세스 할 수 없습니다.

    이것은 당신이 ValidationErrors 트리로 드릴 다운 할 수 있습니다. 내가 이러한 오류에 대한 즉각적인 통찰력을 얻기 위해 찾은 가장 쉬운 방법입니다.

  3. ==============================

    3.경우에 당신은 동일한 속성 이름을 가진 클래스 이곳 프라 빈의 대답에 작은 확장은 다음과 같습니다

    경우에 당신은 동일한 속성 이름을 가진 클래스 이곳 프라 빈의 대답에 작은 확장은 다음과 같습니다

     catch (DbEntityValidationException dbEx)
     {
        foreach (var validationErrors in dbEx.EntityValidationErrors)
        {
           foreach (var validationError in validationErrors.ValidationErrors)
           {
              Trace.TraceInformation(
                    "Class: {0}, Property: {1}, Error: {2}",
                    validationErrors.Entry.Entity.GetType().FullName,
                    validationError.PropertyName,
                    validationError.ErrorMessage);
           }
        }
     }
    
  4. ==============================

    4.프라 빈과 토니 모두에 대한 개선, 나는 재정의를 사용합니다 :

    프라 빈과 토니 모두에 대한 개선, 나는 재정의를 사용합니다 :

    public partial class MyDatabaseEntities : DbContext
    {
        public override int SaveChanges()
        {
            try
            {
                return base.SaveChanges();
            }
            catch (DbEntityValidationException dbEx)
            {
                foreach (var validationErrors in dbEx.EntityValidationErrors)
                {
                    foreach (var validationError in validationErrors.ValidationErrors)
                    {
                        Trace.TraceInformation("Class: {0}, Property: {1}, Error: {2}",
                            validationErrors.Entry.Entity.GetType().FullName,
                            validationError.PropertyName,
                            validationError.ErrorMessage);
                    }
                }
    
                throw;  // You can also choose to handle the exception here...
            }
        }
    }
    
  5. ==============================

    5.세부 텍스트 예외이 구현 랩 엔티티 예외입니다. 그것은 DbEntityValidationException, DbUpdateException, DATETIME2 범위 오류 (MS SQL)를 처리하고 (한 SaveChanges를에서 savind 많은 개체가 호출 할 때 유용) 메시지에 잘못된 엔티티의 키를 포함한다.

    세부 텍스트 예외이 구현 랩 엔티티 예외입니다. 그것은 DbEntityValidationException, DbUpdateException, DATETIME2 범위 오류 (MS SQL)를 처리하고 (한 SaveChanges를에서 savind 많은 개체가 호출 할 때 유용) 메시지에 잘못된 엔티티의 키를 포함한다.

    첫째, DbContext 클래스 SaveChanges를를 오버라이드 (override) :

    public class AppDbContext : DbContext
    {
        public override int SaveChanges()
        {
            try
            {
                return base.SaveChanges();
            }
            catch (DbEntityValidationException dbEntityValidationException)
            {
                throw ExceptionHelper.CreateFromEntityValidation(dbEntityValidationException);
            }
            catch (DbUpdateException dbUpdateException)
            {
                throw ExceptionHelper.CreateFromDbUpdateException(dbUpdateException);
            }
        }   
    
        public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken)
        {
            try
            {
                return await base.SaveChangesAsync(cancellationToken);
            }
            catch (DbEntityValidationException dbEntityValidationException)
            {
                throw ExceptionHelper.CreateFromEntityValidation(dbEntityValidationException);
            }
            catch (DbUpdateException dbUpdateException)
            {
                throw ExceptionHelper.CreateFromDbUpdateException(dbUpdateException);
            }
        }
    

    ExceptionHelper 클래스 :

    public class ExceptionHelper
    {
        public static Exception CreateFromEntityValidation(DbEntityValidationException ex)
        {
            return new Exception(GetDbEntityValidationMessage(ex), ex);
        }
    
        public static string GetDbEntityValidationMessage(DbEntityValidationException ex)
        {
            // Retrieve the error messages as a list of strings.
            var errorMessages = ex.EntityValidationErrors
                .SelectMany(x => x.ValidationErrors)
                .Select(x => x.ErrorMessage);
    
            // Join the list to a single string.
            var fullErrorMessage = string.Join("; ", errorMessages);
    
            // Combine the original exception message with the new one.
            var exceptionMessage = string.Concat(ex.Message, " The validation errors are: ", fullErrorMessage);
            return exceptionMessage;
        }
    
        public static IEnumerable<Exception> GetInners(Exception ex)
        {
            for (Exception e = ex; e != null; e = e.InnerException)
                yield return e;
        }
    
        public static Exception CreateFromDbUpdateException(DbUpdateException dbUpdateException)
        {
            var inner = GetInners(dbUpdateException).Last();
            string message = "";
            int i = 1;
            foreach (var entry in dbUpdateException.Entries)
            {
                var entry1 = entry;
                var obj = entry1.CurrentValues.ToObject();
                var type = obj.GetType();
                var propertyNames = entry1.CurrentValues.PropertyNames.Where(x => inner.Message.Contains(x)).ToList();
                // check MS SQL datetime2 error
                if (inner.Message.Contains("datetime2"))
                {
                    var propertyNames2 = from x in type.GetProperties()
                                            where x.PropertyType == typeof(DateTime) ||
                                                x.PropertyType == typeof(DateTime?)
                                            select x.Name;
                    propertyNames.AddRange(propertyNames2);
                }
    
                message += "Entry " + i++ + " " + type.Name + ": " + string.Join("; ", propertyNames.Select(x =>
                    string.Format("'{0}' = '{1}'", x, entry1.CurrentValues[x])));
            }
            return new Exception(message, dbUpdateException);
        }
    }
    
  6. ==============================

    6.이 코드는 내 엔티티 검증하는 오류와 문제가있을 때 내 문제를 찾을 수있었습니다. 그것은 나의 엔티티 정의와 나에게 정확한 문제를 말했다. 당신이) (커버 storeDB.SaveChanges에 필요로하는 곳에 코드를 다음보십시오; 시도의 catch 블록을 다음있다.

    이 코드는 내 엔티티 검증하는 오류와 문제가있을 때 내 문제를 찾을 수있었습니다. 그것은 나의 엔티티 정의와 나에게 정확한 문제를 말했다. 당신이) (커버 storeDB.SaveChanges에 필요로하는 곳에 코드를 다음보십시오; 시도의 catch 블록을 다음있다.

      try
    {
             if (TryUpdateModel(theEvent))
             {
                 storeDB.SaveChanges();
                 return RedirectToAction("Index");
             }
    }
    catch (System.Data.Entity.Validation.DbEntityValidationException dbEx)
    {
        Exception raise = dbEx;
        foreach (var validationErrors in dbEx.EntityValidationErrors)
        {
            foreach (var validationError in validationErrors.ValidationErrors)
            {
                string message = string.Format("{0}:{1}", 
                    validationErrors.Entry.Entity.ToString(),
                    validationError.ErrorMessage);
                // raise a new exception nesting
                // the current instance as InnerException
                raise = new InvalidOperationException(message, raise);
            }
        }
        throw raise;
    }
    
  7. ==============================

    7.오늘은이 오류를 얻고 있었다 잠시 동안 그것을 밖으로 작동하지 않을 수 있습니다,하지만 난 내 모델 및 일부 개발 종자 데이터가 필요한 모든 필드를 채우는되지 않았 음을 몇 가지 RequireAttributes를 추가 한 후 깨달았다. 당신이 DropCreateDatabaseIfModelChanges 같은 초기화 전략의 일종을 통해 데이터베이스를 업데이트하는 동안이 오류가 발생하는 경우 다음 확인해야한다는 그러니 그냥 메모 당신의 씨앗 데이터 만족 만족 어떤 모델 데이터 유효성 검사 속성을.

    오늘은이 오류를 얻고 있었다 잠시 동안 그것을 밖으로 작동하지 않을 수 있습니다,하지만 난 내 모델 및 일부 개발 종자 데이터가 필요한 모든 필드를 채우는되지 않았 음을 몇 가지 RequireAttributes를 추가 한 후 깨달았다. 당신이 DropCreateDatabaseIfModelChanges 같은 초기화 전략의 일종을 통해 데이터베이스를 업데이트하는 동안이 오류가 발생하는 경우 다음 확인해야한다는 그러니 그냥 메모 당신의 씨앗 데이터 만족 만족 어떤 모델 데이터 유효성 검사 속성을.

    나는 이것이 문제의 문제에 대한 약간 다른 것을 알고,하지만 난 내 자신과 같은 문제를 가진 다른 사람에 대한 대답에 조금 더 추가 할 거라고 생각 그래서 인기있는 질문입니다. 이 다른 사람을 도움이되기를 바랍니다 :)

  8. ==============================

    8.나는 () 작업이이를 중앙 집중화하는 것이 좋습니다, 좋은 방법이 아닙니다 모든 SaveChanges를위한 시도 / 캐치를 추가 생각 :

    나는 () 작업이이를 중앙 집중화하는 것이 좋습니다, 좋은 방법이 아닙니다 모든 SaveChanges를위한 시도 / 캐치를 추가 생각 :

    주요 DbContext 클래스에이 클래스를 추가 :

    public override int SaveChanges()
    {
        try
        {
            return base.SaveChanges();
        }
        catch (DbEntityValidationException ex)
        {
            string errorMessages = string.Join("; ", ex.EntityValidationErrors.SelectMany(x => x.ValidationErrors).Select(x => x.ErrorMessage));
            throw new DbEntityValidationException(errorMessages);
        }
    }
    

    이것은 당신의 문맥의 SaveChanges를 () 메소드를 덮어 쓰게됩니다 및 쉼표가 모든 엔티티 유효성 검사 오류를 포함하는 목록을 구분 얻을 수 있습니다.

    이 또한이 대신 오류를 던지는, 생산 ENV에 오류를 기록, 개선 할 수 있습니다.

    이 도움이되기를 바랍니다.

  9. ==============================

    9.다음은 토니의 확장에 대한 확장입니다 ... :-)

    다음은 토니의 확장에 대한 확장입니다 ... :-)

    당신은 문제가있는 엔티티 인스턴스 (DB 기록) 알 수 있도록 키 필드의 이름과 값을 얻으려면 엔티티 프레임 워크 4.x를 들어, 다음을 추가 할 수 있습니다. 이것은 당신의 DbContext 객체에서 더 강력한 ObjectContext를 클래스 멤버에 대한 액세스를 제공합니다.

    // Get the key field name & value.
    // This assumes your DbContext object is "_context", and that it is a single part key.
    var e = ((IObjectContextAdapter)_context).ObjectContext.ObjectStateManager.GetObjectStateEntry(validationErrors.Entry.Entity);
    string key = e.EntityKey.EntityKeyValues[0].Key;
    string val = e.EntityKey.EntityKeyValues[0].Value;
    
  10. ==============================

    10.나는 예외를 좋아하지 않는다 나는에 SaveChanges를 등록이 있습니다

    나는 예외를 좋아하지 않는다 나는에 SaveChanges를 등록이 있습니다

    var validationErrors = model.GetValidationErrors();
    
    var h = validationErrors.SelectMany(x => x.ValidationErrors
                                              .Select(f => "Entity: " 
                                                          +(x.Entry.Entity) 
                                                          + " : " + f.PropertyName 
                                                          + "->" + f.ErrorMessage));
    
  11. ==============================

    11.당신이 유효성 검사 오류가있는 개체를 저장하려고하면이 오류가 발생합니다. 이 문제를 야기하는 좋은 방법은 DB에 저장하기 전에 ModelState.IsValid을 확인하는 것을 잊지하는 것입니다.

    당신이 유효성 검사 오류가있는 개체를 저장하려고하면이 오류가 발생합니다. 이 문제를 야기하는 좋은 방법은 DB에 저장하기 전에 ModelState.IsValid을 확인하는 것을 잊지하는 것입니다.

  12. ==============================

    12.당신은 DB 행에 NVARCHAR (50)이있는 경우 당신이 그것을에서 50characters보다 더 삽입을 시도하지 않습니다 있는지 확인하십시오. 하지만 바보 같은 실수를 알아 내기 위해 나에게 3 시간 걸렸다.

    당신은 DB 행에 NVARCHAR (50)이있는 경우 당신이 그것을에서 50characters보다 더 삽입을 시도하지 않습니다 있는지 확인하십시오. 하지만 바보 같은 실수를 알아 내기 위해 나에게 3 시간 걸렸다.

  13. ==============================

    13.이것은 지정된보다 더 데이터 형식 NVARCHAR (5)하지만 사용자로부터 입력 된 문자의 수를 다음 수도 인해 SQL 하나의 필드처럼, 특정 컬럼에 허용되는 최대 문자 수를 수 있습니다, 따라서 오류가 발생합니다.

    이것은 지정된보다 더 데이터 형식 NVARCHAR (5)하지만 사용자로부터 입력 된 문자의 수를 다음 수도 인해 SQL 하나의 필드처럼, 특정 컬럼에 허용되는 최대 문자 수를 수 있습니다, 따라서 오류가 발생합니다.

  14. ==============================

    14.나는 데이터베이스를 업데이트 얼마 전 같은 문제를 며칠에 직면했다. 내 경우에는 예외의 원인이되는 코드에서 제공되지 않은 유지 보수를 위해 추가 된 몇 가지 새로운 비 널 (NULL) 컬럼이 있었다. 나는 그들과 그 해결을위한 해당 필드 및 공급 값을 알아낼.

    나는 데이터베이스를 업데이트 얼마 전 같은 문제를 며칠에 직면했다. 내 경우에는 예외의 원인이되는 코드에서 제공되지 않은 유지 보수를 위해 추가 된 몇 가지 새로운 비 널 (NULL) 컬럼이 있었다. 나는 그들과 그 해결을위한 해당 필드 및 공급 값을 알아낼.

  15. ==============================

    15.귀하의 답변 Thnaks, 그것은 많이 도와주세요. Vb.Net에서 나는 코드로,이 볼트 코드 Vb.Net

    귀하의 답변 Thnaks, 그것은 많이 도와주세요. Vb.Net에서 나는 코드로,이 볼트 코드 Vb.Net

    Try
       Return MyBase.SaveChanges()
    Catch dbEx As Validation.DbEntityValidationException
       For Each [error] In From validationErrors In dbEx.EntityValidationErrors
                           From validationError In validationErrors.ValidationErrors
                           Select New With { .PropertyName = validationError.PropertyName,
                                             .ErrorMessage = validationError.ErrorMessage,
                                             .ClassFullName = validationErrors.Entry.Entity
                                                                        .GetType().FullName}
    
            Diagnostics.Trace.TraceInformation("Class: {0}, Property: {1}, Error: {2}",
                                               [error].ClassFullName,
                                               [error].PropertyName,
                                               [error].ErrorMessage)
       Next
       Throw
    End Try
    
  16. ==============================

    16.그것은이 오류가 ..이 해결책이 ModelState 유효성 검사를 적용하기 전에 재산을 할당되어 발생할 수있는 .. 대신이 컨트롤러에 의해 채워집니다 .. 모델에 의해 채워지지 않습니다 재산권에 의해 발생 할 수 있습니다. 이 제 가정한다. 당신은 이미 데이터베이스에 데이터를 모른다    그것에게 그것을 업데이트하려고하지만 지금은 그것을 가져 오는.

    그것은이 오류가 ..이 해결책이 ModelState 유효성 검사를 적용하기 전에 재산을 할당되어 발생할 수있는 .. 대신이 컨트롤러에 의해 채워집니다 .. 모델에 의해 채워지지 않습니다 재산권에 의해 발생 할 수 있습니다. 이 제 가정한다. 당신은 이미 데이터베이스에 데이터를 모른다    그것에게 그것을 업데이트하려고하지만 지금은 그것을 가져 오는.

  17. ==============================

    17.내 경우에는 내가 데이터 형식 내가 세트 VARCHAR (200)이었다 테이블 열 이름 경로 후론은 (최대) NVARCHAR로 갱신이, 나는 edmx에서 테이블을 삭제 한 후 다시 테이블을 추가하고 나를 위해 제대로 wokred있다.

    내 경우에는 내가 데이터 형식 내가 세트 VARCHAR (200)이었다 테이블 열 이름 경로 후론은 (최대) NVARCHAR로 갱신이, 나는 edmx에서 테이블을 삭제 한 후 다시 테이블을 추가하고 나를 위해 제대로 wokred있다.

  18. from https://stackoverflow.com/questions/5400530/validation-failed-for-one-or-more-entities-while-saving-changes-to-sql-server-da by cc-by-sa and MIT license