EF Code First: Как я могу увидеть свойство EntityValidationErrors из консоли пакета nuget?
Я затрудняюсь для этого:
Я определил свои классы для первого подхода кода рамки сущности (4.1.3). Все было хорошо (я создавал таблицы и т.д.), Пока я не начал Seed.
Теперь, когда я делаю
Add-Migration "remigrate" ; Update-Database;
Я получаю сообщение об ошибке на консоли пакета "Не удалось выполнить проверку для одного или нескольких объектов. Подробнее см." Свойство EntityValidationErrors ".
У меня есть точка останова в моем методе Seed(), но поскольку я запускаю это на консоли, когда проект не запущен, я не знаю, как добраться до деталей (PS - я видел thread Не удалось выполнить проверку для одного или нескольких объектов при сохранении изменений в базе данных SQL Server с использованием Entity Framework, которая показывает, как я могу увидеть свойство.)
Я знаю, что у моего метода Seed() есть проблема, потому что, если я поместил return сразу после вызова метода, ошибка исчезнет. Итак, как мне установить точку останова, чтобы я мог видеть, что такое ошибка проверки? Кинда проиграл. Или есть какой-то другой способ проследить его в консоли nuget?
Ответы
Ответ 1
Меня тоже это раздражало. Я исправил его, поместив функцию-оболочку в класс Configuration в методе 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)
в методе семян.
Ответ 2
Расширьте класс 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 }
Вся идея с частичными классами - если вы заметили, что DbContext - это частичный класс, - это то, что вы можете расширить класс, который был сгенерирован (или организовать классы в несколько файлов) и в в нашем случае мы также хотим переопределить метод СохранитьChanges из частичного класса, который добавляет к DbContext.
Таким образом, мы можем получать информацию об отладке ошибок из всех существующих вызовов DbContext/SaveChanges во всем мире и вообще не менять код семени или код разработки.
Это то, что я сделал бы ( ПРИМЕЧАНИЕ. Разница в том, что я просто переопределяю метод SaveChanges в нашем собственном автономном классе DbContext, а не GENERATED ONE). Кроме того, убедитесь, что частичный класс использует правильное пространство имен, или вы будете стучать головой о стену.
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
Я преобразовал ответ Ричардса в метод расширения:
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 в С# мне пришлось добавить 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());
}
Ответ 5
Ричард благодарит меня за то, что нашел меня на правильном пути (имел такую же проблему) ниже, является альтернативой без оболочки, которая сработала для меня в методе семантики конфигурации миграции:
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
Было ли возможно видеть исключение в консоли диспетчера пакетов. Надеюсь, это поможет кому-то.
Ответ 6
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