programing

Entity Framework를 사용하여 SQL Server 데이터베이스의 변경 내용을 저장하는 동안 하나 이상의 엔티티에 대한 유효성 검사에 실패했습니다.

powerit 2023. 4. 28. 21:44
반응형

Entity Framework를 사용하여 SQL Server 데이터베이스의 변경 내용을 저장하는 동안 하나 이상의 엔티티에 대한 유효성 검사에 실패했습니다.

편집 내용을 데이터베이스에 저장하고 ASP에서 Entity Framework Code-First를 사용하고 있습니다.NET MVC 3 / C# 그런데 오류가 발생합니다.이벤트 클래스에는 DateTime 및 TimeSpan 데이터 유형이 있지만 데이터베이스에는 Date 및 TimeSpan 데이터 유형이 각각 있습니다.이것이 이유일까요?변경사항을 데이터베이스에 저장하기 전에 코드의 해당 데이터 유형에 캐스트하려면 어떻게 해야 합니까?

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

컨트롤러의 메서드 >>>> 스토어 DB에서 문제가 발생했습니다.변경 내용 저장();

// 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' 속성을 참조하십시오.

설명:현재 웹 요청을 실행하는 동안 처리되지 않은 예외가 발생했습니다.오류에 대한 자세한 내용과 코드에서 발생한 오류에 대한 자세한 내용은 스택 추적을 검토하십시오.

예외 세부 정보:시스템.데이터. 엔티티.확인.DbEntity 검증예외:하나 이상의 엔티티에 대해 유효성 검사에 실패했습니다.자세한 내용은 '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

스택 추적:

[DbEntity 검증]예외:하나 이상의 엔티티에 대해 유효성 검사에 실패했습니다.자세한 내용은 '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" 창(+)CtrlAltQ을 열고 다음을 붙여넣습니다.

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

또는:

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

시도/캐치에 있지 않거나 예외 개체에 액세스할 수 없는 경우.

이를통아드수있다니습할운릴다에 대해 알아볼 수 .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 errors(MS 키 를 하나의 엔터티에 할 때 )SaveChanges을 합니다.

첫째, 재의를 재정의합니다.SaveChanges 클래스DbContext 파일:

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

예외.도우미 클래스:

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

이 코드는 엔티티 검증 오류 문제가 발생했을 때 문제를 찾는 데 도움이 되었습니다.그것은 나의 엔티티 정의에 대한 정확한 문제를 말해주었습니다.스토어 DB를 다룰 필요가 있는 코드를 따라 해보십시오.변경 사항 저장(); 다음 시도 캐치 블록에서.

  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일부 개발 시드 데이터가 필수 필드를 모두 채우지 않았다는 점과 모델에 대해 설명합니다.
따라서 다음과 같은 종류의 init 전략을 통해 데이터베이스를 업데이트하는 동안 이 오류가 발생하면 주의하십시오.DropCreateDatabaseIfModelChanges그런 다음 시드 데이터가 모델 데이터 유효성 검사 속성을 충족하고 충족하는지 확인해야 합니다.

저는 이것이 질문의 문제와 약간 다르다는 것을 알지만, 그것은 인기 있는 질문이기 때문에 저와 같은 문제를 가지고 있는 다른 사람들을 위해 답에 조금 더 추가하려고 생각했습니다.
이것이 다른 사람들에게 도움이 되기를 바랍니다 :)

다음 시간마다 시도/캐치를 추가하는 것이 좋습니다.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()메서드를 선택하면 모든 엔티티 유효성 검사 오류가 포함된 쉼표로 구분된 목록이 표시됩니다.

또한 오류를 발생시키는 대신 운영 환경에 오류를 기록할 수 있습니다.

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

토니의 내선번호를 알려드립니다... :-)

Entity Framework 4.x의 경우 어떤 엔티티 인스턴스(DB 레코드)에 문제가 있는지 알 수 있도록 키 필드의 이름과 값을 가져오려면 다음을 추가할 수 있습니다.이렇게 하면 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;

예외를 좋아하지 않습니다. OnSaveChanges를 등록하고 이를 가지고 있습니다.

var validationErrors = model.GetValidationErrors();

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

이 오류는 유효성 검사 오류가 있는 엔티티를 저장하려고 할 때도 발생합니다.이 문제를 발생시키는 좋은 방법은 모델 상태를 확인하는 것을 잊는 것입니다.DB에 저장하기 전에 유효합니다.

DB 행에 nvarchar(50)가 있는 경우, 50자 이상을 삽입하지 않도록 하십시오.바보 같은 실수였지만 그걸 알아내는 데 3시간이 걸렸습니다.

답변해 주셔서 감사합니다. 제가 Vb로 코딩하는 것처럼 많은 도움이 됩니다.네트, 이 볼트 코드는 Vb입니다.그물

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

모델별로 채워지지 않은 속성으로 인해 발생할 수 있습니다.대신 컨트롤러에 의해 채워집니다.이 오류가 발생할 수 있습니다.이에 대한 해결책은 ModelState 검증을 적용하기 전에 속성을 할당하는 것입니다.그리고 이 두 번째 가정은 .데이터가 이미 데이터베이스에 있고 업데이트를 시도하지만 지금은 데이터를 가져오는 중입니다.

이는 sql에서 하나의 필드에 다음과 같은 데이터 유형이 있을 수 있는 것처럼 특정 열에 허용되는 최대 문자 수 때문일 수 있습니다.nvarchar(5)그러나 사용자가 입력한 문자 수가 지정된 문자 수보다 많아 오류가 발생합니다.

저는 며칠 전에 데이터베이스를 업데이트하는 동안 같은 문제에 직면한 적이 있습니다.저의 경우, 예외를 유발하는 코드에 제공되지 않은 유지관리를 위해 추가된 null이 아닌 새 열이 거의 없었습니다.저는 그 필드들과 그 필드들에 대한 제공된 값들을 파악하고 해결했습니다.

제 경우에는 테이블 열 이름 경로가 있습니다. 데이터 유형은 varchar(200)로 설정되었습니다.nvarchar(max)로 업데이트한 후 edmx에서 테이블을 삭제하고 다시 테이블을 추가했더니 제대로 작동했습니다.

언급URL : https://stackoverflow.com/questions/5400530/validation-failed-for-one-or-more-entities-while-saving-changes-to-sql-server-da

반응형