C#中EntityFramework常见报错汇总
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
C#中EntityFramework常见报错汇总以下⼩编整理的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")
{
zyLoadingEnabled = 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@",
};
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@",
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@",
};
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@",
};
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@",
};
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@",
};
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@",
Nickname = "TestUpdateErrorTestUpdateErrorTestUpdateErrorTestUpdateErrorTestUpdateErrorTestUpdateErrorTestUpdateErrorTestUpdateErrorTestUpdateErrorTestUpdateErrorTestUpdateError" };
DbEntityEntry<User> entry = db.Entry<User>(user);
entry.State = EntityState.Unchanged;
entry.Property(t => t.Email).IsModified = true;
int num = db.SaveChanges();
}
运⾏程序报错:
⼀层⼀层点开,查看具体原因:。