[asp.net-mvc-3] EF 코드 우선 : 너겟 패키지 콘솔에서 ‘EntityValidationErrors’속성을 어떻게 볼 수 있습니까?

나는 이것을 잃어 버렸다.

엔티티 프레임 워크 (4.1.3) 코드 첫 번째 접근 방식에 대한 클래스를 정의했습니다. 내가 씨앗을 시작할 때까지 모든 것이 잘되었습니다 (테이블 등을 만들고있었습니다).

이제 내가 할 때

Add-Migration "remigrate" ; Update-Database;

패키지 콘솔에 “하나 이상의 엔터티에 대한 유효성 검사에 실패했습니다. 자세한 내용은 ‘EntityValidationErrors’속성을 참조하십시오.”라는 오류가 발생합니다.

내 Seed () 메서드에 중단 점이 있지만 프로젝트가 실행되고 있지 않을 때 콘솔에서이를 실행하기 때문에 세부 정보를 얻는 방법에 대한 단서가 없습니다 (PS-스레드 유효성 검사에 실패했습니다. Entity Framework사용하여 SQL Server 데이터베이스에 변경 사항을 저장하는 동안 하나 이상의 엔터티에 대해 속성을 볼 수있는 방법을 보여줍니다.)

메서드 호출 직후에 반환하면 오류가 사라지기 때문에 Seed () 메서드에 문제가 있음을 알고 있습니다. 그렇다면 유효성 검사 오류가 무엇인지 알 수 있도록 중단 점을 어떻게 설정합니까? 졌어요 아니면 너겟 콘솔에서 추적 할 수있는 다른 방법이 있습니까 ??



답변

최근에도 이것에 짜증이났습니다. Seed 메서드의 Configuration 클래스에 래퍼 함수를 ​​넣어서 수정하고 SaveChanges대신 호출을 내 함수 호출로 대체 했습니다. 이 함수는 단순히 EntityValidationErrors콜렉션 내의 오류를 열거 하고 예외 메시지가 개별 문제점을 나열하는 예외를 다시 발생시킵니다. 그러면 NuGet 패키지 관리자 콘솔에 출력이 표시됩니다.

코드는 다음과 같습니다.

/// <summary>
/// Wrapper for SaveChanges adding the Validation Messages to the generated exception
/// </summary>
/// <param name="context">The context.</param>
private void SaveChanges(DbContext context) {
    try {
        context.SaveChanges();
    } catch (DbEntityValidationException ex) {
        StringBuilder sb = new StringBuilder();

        foreach (var failure in ex.EntityValidationErrors) {
            sb.AppendFormat("{0} failed validation\n", failure.Entry.Entity.GetType());
            foreach (var error in failure.ValidationErrors) {
                sb.AppendFormat("- {0} : {1}", error.PropertyName, error.ErrorMessage);
                sb.AppendLine();
            }
        }

        throw new DbEntityValidationException(
            "Entity Validation Failed - errors follow:\n" +
            sb.ToString(), ex
        ); // Add the original exception as the innerException
    }
}

seed 메소드에서 호출을 context.SaveChanges()로 바꾸 SaveChanges(context)십시오.


답변

부분 클래스 정의로 DBContext 클래스를 이미 확장하십시오!

DbContext의 클래스 정의를 보면 다음과 같습니다.

// DatabaseContext.cs   -- This file is auto generated and thus shouldn't be changed. 
public partial class [DatabaseContextName] : DbContext { ... }

따라서 다른 파일에서 동일한 정의를 작성하고 원하는 부분을 대체 할 수 있습니다.

// partialDatabaseContext.cs  -- you can safely make changes 
// that will not be overwritten in here.
public partial class [DatabaseContextName] : DbContext { // Override defaults here } 

부분 클래스와 전체 아이디어는 당신이 알 –did DbContext이 부분 그 수업은 당신이 생성 된 클래스를 확장 (또는 여러 개의 파일로 클래스를 구성하는) 우리의 경우 우리는 또한 할 수 있다는 것입니다 오버라이드 (override) SaveChanges를의 방법을 DbContext에 추가하는 부분 클래스 내에서 .

이 방법으로 모든 기존 DbContext / SaveChanges 호출에서 오류 디버깅 정보를 얻을 수 있으며 시드 코드 또는 개발 코드를 전혀 변경할 필요가 없습니다.

이것은 (내가 할 것 인 것이다 참고 차이가 난 그냥 저작 우리 자신에 SaveChanges를 메소드를 오버라이드 (override)이다 DbContext에게 부분 클래스, NOT 생성 된 하나 ). 또한 부분 클래스가 올바른 네임 스페이스를 사용하는지 확인하십시오. 그렇지 않으면 벽에 머리가 부딪 칠 것입니다.

public partial class Database : DbContext
{
    public override int SaveChanges()
    {
        try
        {
            return base.SaveChanges();
        }
        catch (DbEntityValidationException ex)
        {
            var sb = new StringBuilder();

            foreach (var failure in ex.EntityValidationErrors)
            {
                sb.AppendFormat("{0} failed validation\n", failure.Entry.Entity.GetType());
                foreach (var error in failure.ValidationErrors)
                {
                    sb.AppendFormat("- {0} : {1}", error.PropertyName, error.ErrorMessage);
                    sb.AppendLine();
                }
            }

            throw new DbEntityValidationException(
                "Entity Validation Failed - errors follow:\n" +
                sb.ToString(), ex
                ); // Add the original exception as the innerException
        }
    }
}


답변

Richards 답변을 확장 방법으로 변환했습니다.

  public static int SaveChangesWithErrors(this DbContext context)
    {
        try
        {
            return context.SaveChanges();
        }
        catch (DbEntityValidationException ex)
        {
            StringBuilder sb = new StringBuilder();

            foreach (var failure in ex.EntityValidationErrors)
            {
                sb.AppendFormat("{0} failed validation\n", failure.Entry.Entity.GetType());
                foreach (var error in failure.ValidationErrors)
                {
                    sb.AppendFormat("- {0} : {1}", error.PropertyName, error.ErrorMessage);
                    sb.AppendLine();
                }
            }

            throw new DbEntityValidationException(
                "Entity Validation Failed - errors follow:\n" +
                sb.ToString(), ex
            ); // Add the original exception as the innerException
        }
    }

이런 식으로 전화하십시오 :

context.SaveChangesWithErrors();


답변

craigvl의 버전을 C #으로 변환했는데 context.SaveChanges (); 다음과 같이 나를 위해 작동합니다.

try
{
    byte[] bytes = System.IO.File.ReadAllBytes(@"C:\Users\sheph_000\Desktop\Rawr.png");
    Console.WriteLine(bytes);

    context.BeverageTypes.AddOrUpdate(
        x => x.Name,
        new AATPos.DAL.Entities.BeverageType { ID = 1, Name = "Sodas" }
        );

    context.Beverages.AddOrUpdate(
        x => x.Name,
        new AATPos.DAL.Entities.Beverage { ID = 1, Name = "Coke", BeverageTypeID = 1, ImageData = bytes, IsStocked = true, StockLevel = 10, Price = 10.00M, ImageMimeType = "test" },
        new AATPos.DAL.Entities.Beverage { ID = 2, Name = "Fanta", BeverageTypeID = 1, ImageData = bytes, IsStocked = true, StockLevel = 10, Price = 10.00M, ImageMimeType = "test" },
        new AATPos.DAL.Entities.Beverage { ID = 3, Name = "Sprite", BeverageTypeID = 1, ImageData = bytes, IsStocked = true, StockLevel = 10, Price = 10.00M, ImageMimeType = "test" },
        new AATPos.DAL.Entities.Beverage { ID = 4, Name = "Cream Soda", BeverageTypeID = 1, ImageData = bytes, IsStocked = true, StockLevel = 10, Price = 10.00M, ImageMimeType = "test" },
        new AATPos.DAL.Entities.Beverage { ID = 5, Name = "Pepsi", BeverageTypeID = 1, ImageData = bytes, IsStocked = true, StockLevel = 10, Price = 10.00M, ImageMimeType = "test" }
        );

    context.SaveChanges();
}
catch (System.Data.Entity.Validation.DbEntityValidationException ex)
{
    var sb = new System.Text.StringBuilder();
    foreach (var failure in ex.EntityValidationErrors)
            {
                sb.AppendFormat("{0} failed validation", failure.Entry.Entity.GetType());
        foreach (var error in failure.ValidationErrors)
                {
            sb.AppendFormat("- {0} : {1}", error.PropertyName, error.ErrorMessage);
            sb.AppendLine();
                }
            }

    throw new Exception(sb.ToString());
}


답변

아래의 올바른 경로를 찾아 주셔서 감사합니다. (같은 문제가 있음) 마이그레이션 구성 시드 방법에서 나에게 도움이되는 래퍼가없는 대안입니다.

 Protected Overrides Sub Seed(context As NotificationContext)

        Try
            context.System.AddOrUpdate(
               Function(c) c.SystemName,
                New E_NotificationSystem() With {.SystemName = "System1"},
                New E_NotificationSystem() With {.SystemName = "System2"},
                New E_NotificationSystem() With {.SystemName = "System3"})

            context.SaveChanges()

        Catch ex As DbEntityValidationException

            Dim sb As New StringBuilder

            For Each failure In ex.EntityValidationErrors

                sb.AppendFormat("{0} failed validation" & vbLf, failure.Entry.Entity.[GetType]())

                For Each [error] In failure.ValidationErrors
                    sb.AppendFormat("- {0} : {1}", [error].PropertyName, [error].ErrorMessage)
                    sb.AppendLine()
                Next
            Next

            Throw New Exception(sb.ToString())

        End Try
End Sub

그런 다음 패키지 관리자 콘솔에서 예외를 볼 수있었습니다. 이것이 누군가를 돕기를 바랍니다.


답변

I Also had same model validation problem but successfully catch by myself after lot of thinking;

I use reverse engineering method to catch the problem out of Over 80 + Model Classes;

1> Made copy of dbcontext, changing the name (I add "1" at end and make respective changes in class constructor and initialization etc.

Old:

>public class AppDb : IdentityDbContext<ApplicationUser>
>
> {
> public AppDb(): base("DefaultConnection", throwIfV1Schema: false)
> {
>
> }
>
> public static AppDb Create()
>{
>return new AppDb();
>}

**New:**

>public class AppDb1 : IdentityDbContext<ApplicationUser>
>{
>public AppDb1()
>: base("DefaultConnection", throwIfV1Schema: false)
>{
>}
>
>public static AppDb1 Create()
> {
> return new AppDb1();
>  }`

...
2> Make changes to Codefirst Migration Configuration from Old DbContext to my new Context.

> internal sealed class Configuration :
> DbMigrationsConfiguration<DAL.AppDb1> { public Configuration() {
> AutomaticMigrationsEnabled = false; }    protected override void
> Seed(DAL.AppDb1 context) {`

3> Comment the Dbsets in new DbContext which was doubt.
4> Apply update migration if succeeded the probelm lye in Commented section.
5> if not then commented section is clear of bug clear.
6> repeat the (4) until found the right place of bug.
7> Happy Codding


답변