Entity Framework를 사용하여 SQL Server 데이터베이스의 변경 사항을 저장하는 동안 하나 이상의 엔터티에 대한 유효성 검사에 실패했습니다 var theEvent = storeDB.Events.Find(id);

편집 내용을 데이터베이스에 저장하고 ASP.NET MVC 3 / C #에서 Entity FrameWork Code-First를 사용하고 있지만 오류가 발생합니다. 내 이벤트 클래스에는 DateTime 및 TimeSpan 데이터 유형이 있지만 데이터베이스에는 각각 Date 및 Time이 있습니다. 이것이 이유가 될 수 있습니까? 변경 사항을 데이터베이스에 저장하기 전에 코드에서 적절한 데이터 유형으로 캐스트하는 방법

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 Server 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 : \ sep \ MvcEventCalendar \ MvcEventCalendar \ Controllers \ EventManagerController.cs 줄 : 77

스택 추적 :

[DbEntityValidationException : 하나 이상의 엔티티에 대한 유효성 검증에 실패했습니다. 자세한 내용은 ‘EntityValidationErrors’속성을 참조하십시오.]



답변

당신은 모든 정보를 추출 할 수있는 DbEntityValidationException다음 코드 (: 당신이 네임 스페이스를 추가 할 필요가와를 System.Data.Entity.Validation하고 System.Diagnostics당신에 using목록) :

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);
        }
    }
}

답변

코드 변경이 필요하지 않습니다.

당신이 내 디버그 모드에있는 동안 catch {...}블록 “QuickWatch”창 ( Ctrl+ Alt+ Q)을 열고 여기에 붙여 넣으십시오.

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

또는:

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

try / catch에 없거나 예외 개체에 액세스 할 수없는 경우

그러면 ValidationErrors트리 로 드릴 다운 할 수 있습니다 . 이 오류에 대한 즉각적인 통찰력을 얻는 가장 쉬운 방법입니다.


답변

속성 이름이 같은 클래스가있는 경우 Praveen의 답변에 대한 작은 확장이 있습니다.

 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);
       }
    }
 }

답변

Praveen과 Tony의 개선으로 재정의를 사용합니다.

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...
        }
    }
}

답변

이 구현은 엔터티 예외를 세부 사항 텍스트로 예외로 랩핑합니다. 그것은 처리 DbEntityValidationException, DbUpdateException, datetime2범위 오류 (MS SQL) 및 (메시지 하나에 유용 때 savind 많은 개체를 무효 엔티티의 키를 포함SaveChanges 호출).

먼저 SaveChangesDbContext 클래스에서 재정의하십시오 .

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);
    }
}

답변

이 코드는 Entity VAlidation Erros에 문제가있을 때 문제를 찾는 데 도움이되었습니다. 엔터티 정의에 대한 정확한 문제를 알려줍니다. storeDB.SaveChanges ()를 포함해야하는 다음 코드를 시도하십시오. 다음 try 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;
}

답변

오늘이 오류가 발생하여 잠시 동안 해결할 수 없었지만 RequireAttribute모델에 s를 추가 한 후 일부 개발 시드 데이터가 모든 필수 필드를 채우지 않는다는 것을 깨달았습니다 .
따라서 어떤 종류의 초기화 전략을 통해 데이터베이스를 업데이트하는 동안이 오류가 발생 DropCreateDatabaseIfModelChanges하면 시드 데이터가 모델 데이터 유효성 검사 속성을 충족하고 충족시켜야합니다 .

나는 이것이 질문의 문제와 약간 다르다는 것을 알고 있지만 인기있는 질문이므로 나 자신과 같은 문제를 가진 다른 사람들의 대답에 조금 더 추가 할 것이라고 생각했습니다.
희망이 다른 사람들을 돕습니다 🙂