Код EF Перше: Як я бачу властивість "EntityValidationErrors" на консолі пакета nuget?


127

Я в цьому втрачаю:

Я визначив свої класи першим підходом до кодової структури (4.1.3). Все було добре (я створював таблиці тощо), поки я не почав висівати насіння.

Тепер, коли я роблю це

Add-Migration "remigrate" ; Update-Database;

Я отримую помилку на консолі пакета "Не вдалося перевірити для однієї чи декількох сутностей. Детальнішу інформацію див. У властивості EntityValidationErrors".

У мене метод Seed (), але оскільки я запускаю це на консолі, коли проект не працює, я не знаю, як дістатися до деталей (PS - я бачив, що перевірка потоку не вдалася для одного або декількох об'єктів, зберігаючи зміни в базі даних SQL Server за допомогою Entity Framework, який показує, як я бачу властивість.)

Я знаю, що у мого методу Seed () є проблема, оскільки якщо я поставив повернення відразу після виклику методу, помилка усувається. Тож як встановити свою точку розриву, щоб я міг бачити, що таке помилка перевірки? Свого роду програв. Або є якийсь інший спосіб простежити це в конфігурації нугетів ??


Швидке оновлення: я вирішив свою проблему систематичним відстеженням кожної змінної в моєму методі, поки я не виявив, що викликає помилку. Однак я все-таки хотів би знати відповідь на моє запитання, як це було б набагато швидше!
Джеремі

Я думаю, ви могли запустити міграцію програмно, а потім вилучити виняток і повторити помилки. Це не ідеально, але може дати вам необхідні деталі.
Pawel

Розчарування, коли неправильна відповідь знаходиться у верхній частині відповідей і отримує всю оцінку. Місце, де StackOverflow явно не вистачає!
jwize

Якщо ви використовуєте Entity Framework, ви можете ознайомитися з моєю відповіддю на рішення для “Не вдалося перевірити для однієї або декількох організацій. Докладніше див. У властивості EntityValidationErrors . Сподіваюсь, це допомагає ...
Мурат Йылдиз

Відповіді:


216

Нещодавно мене це дратувало. Я виправив це, додавши функцію обгортки в клас Конфігурація методом Seed і замінив дзвінки на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
    }
}

Просто замініть виклики context.SaveChanges()з SaveChanges(context)в методі насіння.


Річард, нарешті! Хтось із ідеєю. Я повернусь до цього питання, як тільки спробую його.
Джеремі

Це дійсно допомагає відстежувати нападів :)
Емінем

3
Я використовував цю методику, але замість цього застосував переопрацювання змін. public override int SaveChanges() всередині контексту.
Кірстен Жадібність

5
Це більш ефективно, використовуючи часткові заняття, як я відповів нижче.
jwize

1
Якщо ви виконуєте операції UserManager у своєму початковому методі, то ця зміна не включатиме помилки перевірки у висновку, вам потрібно буде замінити методи DBContext SaveChanges, SaveChangesAsync та SaveChangesAsync (CT) відповідно до @jwize відповіді.
Карл

115

Розширіть свій клас 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 часткове class-- є те , що ви можете розширити клас , який був створений (або організовувати заняття на кілька файлів) , а в нашому випадку ми хочемо перевизначити в SaveChanges метод з часткового класу, який додає до DbContext .

Таким чином, ми можемо отримати інформацію про налагодження помилок з усіх існуючих викликів DbContext / SaveChanges скрізь і взагалі не потрібно змінювати код насіння або код розробки.

Це те, що я б робив ( ПРИМІТКА, різниця полягає в тому, що я просто перекриваю метод SaveChanges в нашому власному авторському частковому класі DbContext , а не в ГЕНЕРИРОВАНОМ ОДНОМУ ). Крім того, переконайтеся, що частковий клас використовує правильну область імен, або ви будете вдарятися головою об стіну.

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

Ви геній ...!
Флоріан Ф.

Прекрасне рішення. Люди повинні прочитати всі відповіді, перш ніж подавати заявку.
Гільгерме де Ісус Сантуш

3
Вам також слід перекрити SaveChangesAsync і SaveChangesAsync (CancellationToken) - принаймні, це так з кодом спочатку, не впевнений спочатку про модель / db.
Карл

@jwize. Ваша відповідь допомогла мені в моїй базі даних спочатку моделювати проблеми з обробкою виключень. чудова відповідь
3355307

1
При використанні CodeFirst DbContext явно не створюється. Однак, коли ви використовуєте конструктор, класи DbContext і Entity генеруються і повинні бути замінені за допомогою часткового класу.
jwize

35

Я перетворив відповідь Річардса в метод розширення:

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

4

Я перетворив версію craigvl в C # Мені довелося додати контекст.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());
}

3

Ричард, дякую за те, що мене вивели на правильний шлях (був той самий випуск) нижче - це альтернатива без обгортки, що працювало для мене у насіннєвому методі конфігурації міграції:

 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

Тоді змогла побачити виняток у консолі менеджера пакунків. Сподіваюся, що це комусь допоможе.


-1

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


1
Було б добре, коли ви форматуєте свій код, щоб ваш текст не знаходився всередині кодового блоку.
jmattheis

це, мабуть, найгірша форматована відповідь
stackoverflow, яку
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.