1 实体属性配置为IsRequired()对更新的影响

抛出异常类型DbEntityValidationException

表结构:

实体:

  1. public class User
  2. {
  3. public int Id { get; set; }
  4. /// <summary>
  5. /// 账号
  6. /// </summary>
  7. public string Account { get; set; }
  8. /// <summary>
  9. /// 邮箱
  10. /// </summary>
  11. public string Email { get; set; }
  12. /// <summary>
  13. /// 昵称
  14. /// </summary>
  15. public string Nickname { get; set; }
  16. /// <summary>
  17. /// 头像
  18. /// </summary>
  19. public string AvatarId { get; set; }
  20. /// <summary>
  21. /// 记录插入时间
  22. /// </summary>
  23. public DateTime InsertTime { get; set; }
  24. /// <summary>
  25. /// 记录修改时间
  26. /// </summary>
  27. public DateTime UpdateTime { get; set; }
  28. }

 

实体配置:

  1.        modelBuilder.Entity<User>().Property(u => u.Account)
  2. .IsRequired()
  3. .IsUnicode(false)
  4. .HasMaxLength(50);
  5. modelBuilder.Entity<User>().Property(u => u.Email)
  6. .IsRequired()
  7. .IsUnicode(false)
  8. .HasMaxLength(100);
  9. modelBuilder.Entity<User>().Property(u => u.Nickname)
  10. .IsUnicode(false)
  11. .HasMaxLength(50);
  12. modelBuilder.Entity<User>().Property(u => u.AvatarId)
  13. .IsOptional()
  14. .HasMaxLength(100);

CustomDbContext继承自DbContext

  1. [DbConfigurationType(typeof(MySqlEFConfiguration))]
  2. public class CustomDbContext : DbContext
  3. {
  4. public CustomDbContext()
  5. : base("name=Master")
  6. {
  7. this.Configuration.LazyLoadingEnabled = false;
  8. //DropCreateDatabaseIfModelChanges
  9. //new DropCreateDatabaseAlways<CustomDbContext>()
  10. Database.SetInitializer<CustomDbContext>(null);
  11. }
  12. public DbSet<User> Users { get; set; }
  13. protected override void OnModelCreating(DbModelBuilder modelBuilder)
  14. {
  15. base.OnModelCreating(modelBuilder);
  16. EntityConfiguration.Set(modelBuilder);
  17. }
  18. }

更新操作:

  1. using (CustomDbContext db = new CustomDbContext())
  2. {
  3. User user = new User
  4. {
  5. Id = 1,
  6. Email = "test@1622.com",
  7. };
  8. DbEntityEntry<User> entry = db.Entry<User>(user);
  9. entry.State = EntityState.Unchanged;
  10. entry.Property(t => t.Email).IsModified = true;
  11. int num = db.SaveChanges();
  12. }

执行操作,报错信息如下:

查看EntityValidationErrors

只能看到{System.Data.Entity.Validation.DbEntityValidationResult},没有更详细的信息。

如果将上述代码用try..catch包起来,如下写法:

  1. try
  2. {
  3. //执行代码
  4. }
  5. catch (DbEntityValidationException ex)
  6. {
  7. var e = ex.EntityValidationErrors;
  8. }
  9. catch (Exception ex)
  10. {
  11. }

 

一层一层地打开,看到真正导致异常的原因,看到下面的截图:

分析实体配置发现,Account属性被设置为IsRequired,那么在更新实体的时候,即使不更新这个字段,也要给这个字段赋值,那么赋值后观察:

更新操作代码变为

 

  1. using (CustomDbContext db = new CustomDbContext())
  2. {
  3. User user = new User
  4. {
  5. Id = 1,
  6. Email = "test@1622.com",
  7. Account = "a"
  8. };
  9. DbEntityEntry<User> entry = db.Entry<User>(user);
  10. entry.State = EntityState.Unchanged;
  11. entry.Property(t => t.Email).IsModified = true;
  12. int num = db.SaveChanges();
  13. }

 

经过上述调整后,更新成功。

那么换一个思路,将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

实体属性配置如上例所示。

操作代码:

 

  1. using (CustomDbContext db = new CustomDbContext())
  2. {
  3. User user = new User
  4. {
  5. Id = 1,
  6. Email = "test@132.com",
  7. };
  8. DbEntityEntry<User> entry = db.Entry<User>(user);
  9. entry.State = EntityState.Unchanged;
  10. entry.Property(t => t.Email).IsModified = true;
  11. User user1 = new User
  12. {
  13. Id = 1,
  14. Email = "test@132.com",
  15. };
  16. DbEntityEntry<User> entry1 = db.Entry<User>(user1);
  17. entry1.State = EntityState.Unchanged;
  18. entry1.Property(t => t.Email).IsModified = true;
  19. int num = db.SaveChanges();
  20. }

 

执行操作

涉及到两次修改操作,两次操作构造了两个实例,但是实例的属性Id有相同的值。

 

如果两次操作的是同一个实例,而不是不同的实例,那么不会抛出异常,代码如下:

 

  1. using (CustomDbContext db = new CustomDbContext())
  2. {
  3. User user = new User
  4. {
  5. Id = 1,
  6. Email = "test@132.com",
  7. };
  8. DbEntityEntry<User> entry = db.Entry<User>(user);
  9. entry.State = EntityState.Unchanged;
  10. entry.Property(t => t.Email).IsModified = true;
  11. DbEntityEntry<User> entry1 = db.Entry<User>(user);
  12. entry1.State = EntityState.Unchanged;
  13. entry1.Property(t => t.Email).IsModified = true;
  14. int num = db.SaveChanges();
  15. }

 

3 未给主键赋值或赋给主键一个不存在的值,抛出异常

System.Data.Entity.Infrastructure.DbUpdateConcurrencyException

操作代码如下,其中Id=1这条语句被注掉,Id是主键:

  1. using (CustomDbContext db = new CustomDbContext())
  2. {
  3. User user = new User
  4. {
  5. //Id = 1,
  6. Email = "test@132.com",
  7. };
  8. DbEntityEntry<User> entry = db.Entry<User>(user);
  9. entry.State = EntityState.Unchanged;
  10. entry.Property(t => t.Email).IsModified = true;
  11. int num = db.SaveChanges();
  12. }

运行上述代码,抛出异常信息如下,注意异常类型居然是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。

操作代码如下:

  1. using (CustomDbContext db = new CustomDbContext())
  2. {
  3. User user = new User
  4. {
  5. Id = 4,
  6. Email = "test@132.com",
  7. Nickname = "TestUpdateErrorTestUpdateErrorTestUpdateErrorTestUpdateErrorTestUpdateErrorTestUpdateErrorTestUpdateErrorTestUpdateErrorTestUpdateErrorTestUpdateErrorTestUpdateError"
  8. };
  9. DbEntityEntry<User> entry = db.Entry<User>(user);
  10. entry.State = EntityState.Unchanged;
  11. entry.Property(t => t.Email).IsModified = true;
  12. int num = db.SaveChanges();
  13. }

运行程序报错:

一层一层点开,查看具体原因:

 

 —————————————————————————————–

转载与引用请注明出处。

时间仓促,水平有限,如有不当之处,欢迎指正。

 

版权声明:本文为hdwgxz原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:http://www.cnblogs.com/hdwgxz/p/7897031.html