C#中Entity Framework常见报错汇总
以下小编整理的Entity Framework常见错误的汇总,大家如果还有不明白可以在下面留言区讨论。
1 实体属性配置为IsRequired()对更新的影响
抛出异常类型DbEntityValidationException
表结构:
实体:
public class User { public int Id { get; set; } /// <summary> /// 账号 /// </summary> public string Account { get; set; } /// <summary> /// 邮箱 /// </summary> public string Email { get; set; } /// <summary> /// 昵称 /// </summary> public string Nickname { get; set; } /// <summary> /// 头像 /// </summary> public string AvatarId { get; set; } /// <summary> /// 记录插入时间 /// </summary> public DateTime InsertTime { get; set; } /// <summary> /// 记录修改时间 /// </summary> public DateTime UpdateTime { get; set; } }
实体配置:
modelBuilder.Entity<User>().Property(u => u.Account) .IsRequired() .IsUnicode(false) .HasMaxLength(50); modelBuilder.Entity<User>().Property(u => u.Email) .IsRequired() .IsUnicode(false) .HasMaxLength(100); modelBuilder.Entity<User>().Property(u => u.Nickname) .IsUnicode(false) .HasMaxLength(50); modelBuilder.Entity<User>().Property(u => u.AvatarId) .IsOptional() .HasMaxLength(100);
CustomDbContext继承自DbContext
[DbConfigurationType(typeof(MySqlEFConfiguration))] public class CustomDbContext : DbContext { public CustomDbContext() : base("name=Master") { this.Configuration.LazyLoadingEnabled = false; //DropCreateDatabaseIfModelChanges //new DropCreateDatabaseAlways<CustomDbContext>() Database.SetInitializer<CustomDbContext>(null); } public DbSet<User> Users { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); EntityConfiguration.Set(modelBuilder); } }
更新操作:
using (CustomDbContext db = new CustomDbContext()) { User user = new User { Id = 1, Email = "test@1622.com", }; DbEntityEntry<User> entry = db.Entry<User>(user); entry.State = EntityState.Unchanged; entry.Property(t => t.Email).IsModified = true; int num = db.SaveChanges(); }
执行操作,报错信息如下:
查看EntityValidationErrors,
只能看到{System.Data.Entity.Validation.DbEntityValidationResult},没有更详细的信息。
如果将上述代码用try..catch包起来,如下写法:
try { //执行代码 } catch (DbEntityValidationException ex) { var e = ex.EntityValidationErrors; } catch (Exception ex) { }
一层一层地打开,看到真正导致异常的原因,看到下面的截图:
分析实体配置发现,Account属性被设置为IsRequired,那么在更新实体的时候,即使不更新这个字段,也要给这个字段赋值,那么赋值后观察:
更新操作代码变为
using (CustomDbContext db = new CustomDbContext()) { User user = new User { Id = 1, Email = "test@1622.com", Account = "a" }; DbEntityEntry<User> entry = db.Entry<User>(user); entry.State = EntityState.Unchanged; entry.Property(t => t.Email).IsModified = true; int num = db.SaveChanges(); }
经过上述调整后,更新成功。
那么换一个思路,将Account属性被设置为IsOptional()是不是也可以呢?
修改实体配置,将Account属性设置按如下修改,并注掉上面的Account = "a"
modelBuilder.Entity<User>().Property(u => u.Account)
.IsOptional()
.IsUnicode(false)
.HasMaxLength(50);
执行测试,更改成功。
得出结论:在实体配置时,指定了为必选的字段,那么更新操作时,构造实例一定要对必选(IsRequired())字段赋值。
上述测试中还有一个值得考虑的细节,构造User实例的时候,只对Id,Email进行了赋值,而没有对其他属性进行赋值,那么为什么会成功呢?那么必定是未进行任何设置的实体属性默认是IsOptional()。这跟表结构中的字段类型设置为Not Null有无关联呢,从测试结果看就本类应用无必然联系。
总结:
a.实体配置中指定了实体属性为IsRequired(),更新操作构造类的实例时必对此属性赋值。
b.不进行配置的实体属性默认为IsOptional()
c.表结构中字段是否为Not Null对上述规则无影响。
2 更新报错:
An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.
异常类型:System.Data.Entity.Infrastructure.DbUpdateConcurrencyException
实体属性配置如上例所示。
操作代码:
using (CustomDbContext db = new CustomDbContext()) { User user = new User { Id = 1, Email = "test@132.com", }; DbEntityEntry<User> entry = db.Entry<User>(user); entry.State = EntityState.Unchanged; entry.Property(t => t.Email).IsModified = true; User user1 = new User { Id = 1, Email = "test@132.com", }; DbEntityEntry<User> entry1 = db.Entry<User>(user1); entry1.State = EntityState.Unchanged; entry1.Property(t => t.Email).IsModified = true; int num = db.SaveChanges(); }
执行操作
涉及到两次修改操作,两次操作构造了两个实例,但是实例的属性Id有相同的值。
如果两次操作的是同一个实例,而不是不同的实例,那么不会抛出异常,代码如下:
using (CustomDbContext db = new CustomDbContext()) { User user = new User { Id = 1, Email = "test@132.com", }; DbEntityEntry<User> entry = db.Entry<User>(user); entry.State = EntityState.Unchanged; entry.Property(t => t.Email).IsModified = true; DbEntityEntry<User> entry1 = db.Entry<User>(user); entry1.State = EntityState.Unchanged; entry1.Property(t => t.Email).IsModified = true; int num = db.SaveChanges(); }
3 未给主键赋值或赋给主键一个不存在的值,抛出异常
System.Data.Entity.Infrastructure.DbUpdateConcurrencyException
操作代码如下,其中Id=1这条语句被注掉,Id是主键:
using (CustomDbContext db = new CustomDbContext()) { User user = new User { //Id = 1, Email = "test@132.com", }; DbEntityEntry<User> entry = db.Entry<User>(user); entry.State = EntityState.Unchanged; entry.Property(t => t.Email).IsModified = true; int num = db.SaveChanges(); }
运行上述代码,抛出异常信息如下,注意异常类型居然是System.Data.Entity.Infrastructure.DbUpdateConcurrencyException,看上去像是并发问题,但实际却不是!
Message:
Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.
赋给主键一个不存在的值,令Id=4(在数据库表中不存在Id为4的一条记录)抛出的异常与上面的相同。
4 字段超长抛出异常:System.Data.Entity.Validation.DbEntityValidationException
表中Nickname 字段定义为50个字符,现在赋值超过50。
操作代码如下:
using (CustomDbContext db = new CustomDbContext()) { User user = new User { Id = 4, Email = "test@132.com", Nickname = "TestUpdateErrorTestUpdateErrorTestUpdateErrorTestUpdateErrorTestUpdateErrorTestUpdateErrorTestUpdateErrorTestUpdateErrorTestUpdateErrorTestUpdateErrorTestUpdateError" }; DbEntityEntry<User> entry = db.Entry<User>(user); entry.State = EntityState.Unchanged; entry.Property(t => t.Email).IsModified = true; int num = db.SaveChanges(); }
运行程序报错:
一层一层点开,查看具体原因:
相关文章
- 我们在使用C#做项目的时候,基本上都需要制作登录界面,那么今天我们就来一步步看看,如果简单的实现登录界面呢,本文给出2个例子,由简入难,希望大家能够喜欢。...2020-06-25
- 这篇文章主要介绍了C# 字段和属性的的相关资料,文中示例代码非常详细,供大家参考和学习,感兴趣的朋友可以了解下...2020-11-03
- 这篇文章主要介绍了C#中截取字符串的的基本方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-11-03
- 这篇文章主要介绍了C#实现简单的Http请求的方法,以实例形式较为详细的分析了C#实现Http请求的具体方法,需要的朋友可以参考下...2020-06-25
- 本文给大家分享C#连接SQL数据库和查询数据功能的操作技巧,本文通过图文并茂的形式给大家介绍的非常详细,需要的朋友参考下吧...2021-05-17
- 本文主要介绍了C#中new的几种用法,具有很好的参考价值,下面跟着小编一起来看下吧...2020-06-25
使用Visual Studio2019创建C#项目(窗体应用程序、控制台应用程序、Web应用程序)
这篇文章主要介绍了使用Visual Studio2019创建C#项目(窗体应用程序、控制台应用程序、Web应用程序),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25- 这篇文章主要介绍了C#开发Windows窗体应用程序的简单操作步骤,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-04-12
- 这篇文章主要介绍了C#从数据库读取图片并保存的方法,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下...2021-01-16
- 最近做一个小项目不可避免的需要前端脚本与后台进行交互。由于是在asp.net中实现,故问题演化成asp.net中jiavascript与后台c#如何进行交互。...2020-06-25
- 本文通过例子,讲述了C++调用C#的DLL程序的方法,作出了以下总结,下面就让我们一起来学习吧。...2020-06-25
- 轻松学习C#的基础入门,了解C#最基本的知识点,C#是一种简洁的,类型安全的一种完全面向对象的开发语言,是Microsoft专门基于.NET Framework平台开发的而量身定做的高级程序设计语言,需要的朋友可以参考下...2020-06-25
- 本文主要介绍了C#变量命名规则小结,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-09
- 这篇文章主要介绍了C#绘制曲线图的方法,以完整实例形式较为详细的分析了C#进行曲线绘制的具体步骤与相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
- 本文主要介绍了C# 中取绝对值的函数。具有很好的参考价值。下面跟着小编一起来看下吧...2020-06-25
- 这篇文章主要介绍了c#自带缓存使用方法,包括获取数据缓存、设置数据缓存、移除指定数据缓存等方法,需要的朋友可以参考下...2020-06-25
- 这篇文章主要介绍了c#中(&&,||)与(&,|)的区别详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-06-25
- 这篇文章主要用实例讲解C#递归算法的概念以及用法,文中代码非常详细,帮助大家更好的参考和学习,感兴趣的朋友可以了解下...2020-06-25
- 下面小编就为大家带来一篇C#学习笔记- 随机函数Random()的用法详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
- 这篇文章主要介绍了C#中list用法,结合实例形式分析了C#中list排序、运算、转换等常见操作技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25