试图在种子方法中的 SaveChanges 中找出我的验证错误

Posted

技术标签:

【中文标题】试图在种子方法中的 SaveChanges 中找出我的验证错误【英文标题】:Trying to find out my validation errors in SaveChanges in seed method 【发布时间】:2016-09-10 12:49:56 【问题描述】:

我正在尝试找出在更新数据库时导致验证异常的特定验证错误。我有理由确定罪魁祸首是SaveChanges()。我认为我的 3 个课程中的一个或多个课程中的一个或多个属性有问题。解决异常的唯一方法是发现验证错误。

我是这种调试方式的新手,尽管我对几种不同的语言有经验。我在指示的地方设置了一个断点,这样我就可以看到debug.writeline 结果,但有两个问题:它永远不会在断点处停止,而且我在输出窗口下拉菜单中看不到“调试”。

我不明白什么?有没有更好的方法来捕获验证错误?

这是 configuration.cs 文件中的完整代码。

namespace AlbumSong2.Migrations

    using System;
    using System.Data.Entity;
    using System.Data.Entity.Migrations;
    using System.Data.Entity.Validation;
    using System.Diagnostics;
    using System.Linq;

    internal sealed class Configuration : DbMigrationsConfiguration<AlbumSong2.Model.AlbumDbContext>
    
        public Configuration()
        
            AutomaticMigrationsEnabled = false;
            //if (System.Diagnostics.Debugger.IsAttached == false)
            //    System.Diagnostics.Debugger.Launch();
        

        protected override void Seed(AlbumSong2.Model.AlbumDbContext context)
        
            //  This method will be called after migrating to the latest version.

            //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
            //  to avoid creating duplicate seed data. E.g.
            //
            //    context.People.AddOrUpdate(
            //      p => p.FullName,
            //      new Person  FullName = "Andrew Peters" ,
            //      new Person  FullName = "Brice Lambson" ,
            //      new Person  FullName = "Rowan Miller" 
            //    );
            //
            context.Singers.AddOrUpdate(t => t.SingerName,
                new Singer()  SingerName = "Chuck Negron" ,
                new Singer()  SingerName = "Cory Wells" ,
                new Singer()  SingerName = "Dan Hutton" );
            context.SaveChanges();

            try
            
                context.Albums.AddOrUpdate(t => t.AlbumName,
                    new Album()
                    
                        AlbumName = "Three Dog Night",
                        AlbumTitle = "Seven Separate Fools",
                        Price = 15,
                        aLength = 45,
                        Year = "1972",
                        isUSA = true,
                        CurrentSingerId = 1
                    ,
                    new Album()
                    
                        AlbumName = "Steppenwolf",
                        AlbumTitle = "Cyan",
                        Price = 10,
                        aLength = 35,
                        Year = "1973",
                        isUSA = true,
                        CurrentSingerId = 2
                    ,
                    new Album()
                    
                        AlbumName = "Grand Funk Railroad",
                        AlbumTitle = "It Ain't Easy",
                        Price = 10,
                        aLength = 35,
                        Year = "1970",
                        isUSA = true,
                        CurrentSingerId = 3
                    );
                context.SaveChanges();
            
            catch (DbEntityValidationException e)
            
                foreach (var eve in e.EntityValidationErrors)
                
                    Debug.WriteLine("Entity of type \"0\" in state \"1\" has the following validation errors:",
                        eve.Entry.Entity.GetType().Name, eve.Entry.State);
                    foreach (var ve in eve.ValidationErrors)
                    
                        Debug.WriteLine("- Property: \"0\", Value: \"1\", Error: \"2\"",
                            ve.PropertyName, 
                            eve.Entry.CurrentValues.GetValue<object>(ve.PropertyName),
                            ve.ErrorMessage);
                    
                
                throw;
            

            try
             
            context.Songs.AddOrUpdate(t => t.SongTitle,
                new Song()  SongTitle = "Black and White", sLength = 4, CurrentAlbumId = 1 ,
                new Song()  SongTitle = "Let Me Seranade You", sLength = 3, CurrentAlbumId = 2 ,
                new Song()  SongTitle = "Mama Told Me (Not To Come)", sLength = 3, CurrentAlbumId = 3 );
            context.SaveChanges();
            
            catch (DbEntityValidationException e)
            
                foreach (var eve in e.EntityValidationErrors)
                
                    Debug.WriteLine("Entity of type \"0\" in state \"1\" has the following validation errors:",
                        eve.Entry.Entity.GetType().Name, eve.Entry.State);
                    foreach (var ve in eve.ValidationErrors)
                    
                        Debug.WriteLine("- Property: \"0\", Value: \"1\", Error: \"2\"",
                            ve.PropertyName,
                            eve.Entry.CurrentValues.GetValue<object>(ve.PropertyName), 
                            ve.ErrorMessage);
                    
                
                throw;
            

        
    

专辑类如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace AlbumSong2

    //[Table("Albums")]
    public class Album
    
        public int AlbumId  get; set; 
        [MinLength(5), MaxLength(25), Required]
        public string AlbumName  get; set; 
        [MinLength(5), MaxLength(25), Required]
        public string AlbumTitle  get; set; 
        public string Year  get; set; 
        [Range(10, 50)]
        public int aLength  get; set; 
        [Range(1, 15)]
        public double Price  get; set; 
        public bool isUSA  get; set; 

        //navigation property -> each Album has many Songs, indicating dependent (child) entity
        public List<Song> Songs  get; set; 

        //navigation property -> indicates parent table
        public Singer CurrentSinger  get; set; 

        [ForeignKey("CurrentSinger")]
        public int? CurrentSingerId  get; set; 


    

还有歌曲类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;


namespace AlbumSong2

    //[Table("Songs")]
    public class Song
    
        public int SongId  get; set; 

        [MinLength(2), MaxLength(45)]
        [Required]
        public string SongTitle  get; set; 
        public int sLength  get; set; 

        //navigation property -> indicates parent table
        public Album CurrentAlbum  get; set; 

        [ForeignKey("CurrentAlbum")]
        public int CurrentAlbumId  get; set; 
    

最后是歌手班。 (数据库中的singer表和代码都没有问题。是另外两个我有问题):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace AlbumSong2

    //[Table("Singers")]
    public class Singer
    
        public int SingerId  get; set; 

        [MinLength(5), MaxLength(25)]
        [Required]
        public string SingerName  get; set; 

        //navigation property -> each Singer has many Albums
        public List<Album> Albums  get; set; 
    

这是我的 VS 程序的屏幕截图,显示了断点和验证错误。

【问题讨论】:

可能重复:***.com/q/28858289/861716 【参考方案1】:

我已将 try/catch 例程从配置文件移至 AlbumDbContext,在此我能够成功捕获错误。这是 AlbumDbContext 文件中的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
using System.Data.Entity.Validation;
using System.Text;
using System.Runtime.Remoting.Contexts;

namespace AlbumSong2.Model

    public class AlbumDbContext : DbContext
    
        public AlbumDbContext() : base("AlbumDbConnection2")  
        public IDbSet<Singer> Singers  get; set; 
        public IDbSet<Album> Albums  get; set; 
        public IDbSet<Song> Songs  get; set; 


        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
            
        
    

这是输出!

问题解决了。

【讨论】:

更新:这帮助我解决了我遇到的问题。【参考方案2】:

如果没有达到断点, 那么您不使用该功能/方法或 您的代码无法访问您的函数/方法的那部分。

一个好的调试还包括像 NUnit 这样的东西——用于更大的东西。 或者总是做一个充当日志的控制台窗口。 我认为有很多软件包。 (说明该消息的重要性以及是否必须在日志中)

也许“投掷”也不是一个好的选择。 也许您可以使用 MessageBox(或 ConsoleLog)并打印异常 e。 也许这对你有帮助。

【讨论】:

以上是关于试图在种子方法中的 SaveChanges 中找出我的验证错误的主要内容,如果未能解决你的问题,请参考以下文章

entity framework 使用存储过程删除数据后,还用再使用SaveChanges()保存吗?

在 foreach 循环 c# 中使用 savechanges()

哪些种子用于通用语言中的本机随机数生成器?

在 SaveChanges() 中返回字典

覆盖 SaveChanges 并删除 EF 关系时为 null

由于在同一 SaveChanges 中删除的记录中的值,实体更新在唯一索引上失败