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();
modelBuilder.Entity<User>().Property(u => u.Email)
.IsRequired()
.IsUnicode(false)
.HasMaxLength();
modelBuilder.Entity<User>().Property(u => u.Nickname)
.IsUnicode(false)
.HasMaxLength();
modelBuilder.Entity<User>().Property(u => u.AvatarId)
.IsOptional()
.HasMaxLength();

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 = ,
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 = ,
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 = ,
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 = ,
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 = ,
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 = ,
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();
}

运行程序报错:

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

-----------------------------------------------------------------------------------------

转载与引用请注明出处。

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

Entity Framework——常见报错总结的更多相关文章

  1. web报表工具FineReport使用中遇到的常见报错及解决办法(二)

    web报表工具FineReport使用中遇到的常见报错及解决办法(二) 这里写点抛砖引玉,希望大家能把自己整理的问题及解决方法晾出来,Mark一下,利人利己. 出现问题先搜一下文档上有没有,再看看度娘 ...

  2. java常见报错及解决

    Java常见报错信息: Java 常见异常种类 Java Exception: 1.Error  2.Runtime Exception 运行时异常 3.Exception  4.throw 用户自定 ...

  3. HDFS集群常见报错汇总

    HDFS集群常见报错汇总 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.DataXceiver error processing WRITE_BLOCK operation 报 ...

  4. 03:git常见报错解决方法

    1.1 git常见报错解决方法 1.warning: LF will be replaced by CRLF in .idea/workspace.xml. 参考博客:https://www.cnbl ...

  5. JavaScript 调试常见报错以及原因

    JavaScript 调试常见报错以及原因 测试环境 chrome 版本 66.0.3359.170(正式版本) (64 位) TypeError 类型错误 不是操作符所接受的数据类型. //---- ...

  6. Nginx 常见报错

    Nginx 常见报错 启动报错:[emerg]: bind() to 0.0.0.0:80 failed (98: Address already in use) 原因:这个是nginx重启时经常遇到 ...

  7. Django 连接 MySQL 数据库及常见报错解决

    目录 Django 连接 MySQL数据库及常见报错解决 终端或者数据库管理工具连接 MySQL ,并新建项目所需数据库 安装访问 MySQL 的 Python 模块 Django 相关配置 可能会遇 ...

  8. C语言开发中常见报错的解决方案

    C语言开发中常见报错的解决方案 整理来源于网络,侵权请通知删除.*禁止转载 ---- fatal error C1003: error count exceeds number; stopping c ...

  9. Git常用命令及常见报错:You have not concluded your merge (MERGE_HEAD exists)、清理无效的远程追踪分支

    一.常用命令 切换到master分支:git checkout master 查看已有本地及远程分支:git branch -a(先git pull拉下全部数据) 查看远程分支:git branch ...

随机推荐

  1. Python通过future处理并发

    future初识 通过下面脚本来对future进行一个初步了解:例子1:普通通过循环的方式 import os import time import sys import requests POP20 ...

  2. [js高手之路] 设计模式系列课程 - jQuery的extend插件机制

    这里在之前的文章[js高手之路] 设计模式系列课程 - jQuery的链式调用与灵活的构造函数基础上增加一个extend浅拷贝,可以为对象方便的扩展属性和方法, jquery的插件扩展机制,大致就是这 ...

  3. win10 uwp MVVM 轻量框架

    如果在开发过程,遇到多个页面之间,需要传输信息,那么可能遇到设计的问题.如果因为一个页面内包含多个子页面和多个子页面之间的通信问题找不到一个好的解决方法,那么请看本文.如果因为ViewModel代码越 ...

  4. 读Zepto源码之Data模块

    Zepto 的 Data 模块用来获取 DOM 节点中的 data-* 属性的数据,和储存跟 DOM 相关的数据. 读 Zepto 源码系列文章已经放到了github上,欢迎star: reading ...

  5. [Python] 文科生零基础学编程系列三——数据运算符的基本类别

    上一篇:[Python] 文科生零基础学编程系列二--数据类型.变量.常量的基础概念 下一篇: ※ 程序的执行过程,就是对数据进行运算的过程. 不同的数据类型,可以进行不同的运算, 按照数据运算类型的 ...

  6. SQL&SQLite

    注册博客园有一年多了,每次都是来找点资料,从来没有写过点什么,促使我开始写博客的原因主要有两点 一是在查找资料的过程中,经常需要重复的查找某个知识点,一个知识点时间长了之后总是忘记,这样重复的过程却是 ...

  7. 一个让你想到即可做到的web弹窗/层----Layer

    Layer     layer是一款近年来备受青睐的web弹层组件,她具备全方位的解决方案,致力于服务各水平段的开发人员,您的页面会轻松地拥有丰富友好的操作体验. 在与同类组件的比较中,layer总是 ...

  8. 如何内网搭建NuGet服务器

    NuGet 是.NET程序员熟知的给.NET项目自动配置安装library的工具,它可以直接安装开源社区中的各个公用组件,可以说是非常方便.不过,有些时候,公司内部的公用的基础类库,各个项目都有引用, ...

  9. nvm进行node多版本管理

    写在前面 nvm(nodejs version manager)是nodejs的管理工具,如果你需要快速更新node版本,并且不覆盖之前的版本:或者想要在不同的node版本之间进行切换: 使用nvm来 ...

  10. TIDB 参数解释

    地址:https://github.com/pingcap/docs-cn/blob/master/op-guide/configuration.md#tidb TiDB --store 用来指定 T ...