C#中Entity Framework常見報(bào)錯匯總
以下小編整理的Entity Framework常見錯誤的匯總,大家如果還有不明白可以在下面留言區(qū)討論。
1 實(shí)體屬性配置為IsRequired()對更新的影響
拋出異常類型DbEntityValidationException
表結(jié)構(gòu):

實(shí)體:
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>
/// 記錄插入時(shí)間
/// </summary>
public DateTime InsertTime { get; set; }
/// <summary>
/// 記錄修改時(shí)間
/// </summary>
public DateTime UpdateTime { get; set; }
}
實(shí)體配置:
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();
}
執(zhí)行操作,報(bào)錯信息如下:

查看EntityValidationErrors,
只能看到{System.Data.Entity.Validation.DbEntityValidationResult},沒有更詳細(xì)的信息。
如果將上述代碼用try..catch包起來,如下寫法:
try
{
//執(zhí)行代碼
}
catch (DbEntityValidationException ex)
{
var e = ex.EntityValidationErrors;
}
catch (Exception ex)
{
}
一層一層地打開,看到真正導(dǎo)致異常的原因,看到下面的截圖:

分析實(shí)體配置發(fā)現(xiàn),Account屬性被設(shè)置為IsRequired,那么在更新實(shí)體的時(shí)候,即使不更新這個字段,也要給這個字段賦值,那么賦值后觀察:
更新操作代碼變?yōu)?/p>
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();
}
經(jīng)過上述調(diào)整后,更新成功。
那么換一個思路,將Account屬性被設(shè)置為IsOptional()是不是也可以呢?
修改實(shí)體配置,將Account屬性設(shè)置按如下修改,并注掉上面的Account = "a"
modelBuilder.Entity<User>().Property(u => u.Account)
.IsOptional()
.IsUnicode(false)
.HasMaxLength(50);
執(zhí)行測試,更改成功。
得出結(jié)論:在實(shí)體配置時(shí),指定了為必選的字段,那么更新操作時(shí),構(gòu)造實(shí)例一定要對必選(IsRequired())字段賦值。
上述測試中還有一個值得考慮的細(xì)節(jié),構(gòu)造User實(shí)例的時(shí)候,只對Id,Email進(jìn)行了賦值,而沒有對其他屬性進(jìn)行賦值,那么為什么會成功呢?那么必定是未進(jìn)行任何設(shè)置的實(shí)體屬性默認(rèn)是IsOptional()。這跟表結(jié)構(gòu)中的字段類型設(shè)置為Not Null有無關(guān)聯(lián)呢,從測試結(jié)果看就本類應(yīng)用無必然聯(lián)系。
總結(jié):
a.實(shí)體配置中指定了實(shí)體屬性為IsRequired(),更新操作構(gòu)造類的實(shí)例時(shí)必對此屬性賦值。
b.不進(jìn)行配置的實(shí)體屬性默認(rèn)為IsOptional()
c.表結(jié)構(gòu)中字段是否為Not Null對上述規(guī)則無影響。
2 更新報(bào)錯:
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
實(shí)體屬性配置如上例所示。
操作代碼:
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();
}
執(zhí)行操作

涉及到兩次修改操作,兩次操作構(gòu)造了兩個實(shí)例,但是實(shí)例的屬性Id有相同的值。
如果兩次操作的是同一個實(shí)例,而不是不同的實(shí)例,那么不會拋出異常,代碼如下:
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();
}
運(yùn)行上述代碼,拋出異常信息如下,注意異常類型居然是System.Data.Entity.Infrastructure.DbUpdateConcurrencyException,看上去像是并發(fā)問題,但實(shí)際卻不是!
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.

賦給主鍵一個不存在的值,令I(lǐng)d=4(在數(shù)據(jù)庫表中不存在Id為4的一條記錄)拋出的異常與上面的相同。
4 字段超長拋出異常:System.Data.Entity.Validation.DbEntityValidationException
表中Nickname 字段定義為50個字符,現(xiàn)在賦值超過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();
}
運(yùn)行程序報(bào)錯:
一層一層點(diǎn)開,查看具體原因:
相關(guān)文章
C#二叉搜索樹算法實(shí)現(xiàn)步驟和實(shí)例代碼
二叉搜索樹(Binary?Search?Tree,簡稱BST)是一種節(jié)點(diǎn)有序排列的二叉樹數(shù)據(jù)結(jié)構(gòu),這篇文章主要介紹了C#二叉搜索樹算法實(shí)現(xiàn)步驟和實(shí)例代碼,需要的朋友可以參考下2024-08-08
C#中控件動態(tài)添加事件綁定的時(shí)機(jī)詳解
這篇文章主要給大家介紹了在C#中為控件動態(tài)添加事件綁定的時(shí)機(jī)的相關(guān)資料,文中介紹的非常詳細(xì),對大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面跟著小編一起來學(xué)習(xí)學(xué)習(xí)吧。2017-06-06
利用C#實(shí)現(xiàn)獲取當(dāng)前設(shè)備硬件信息
這篇文章主要為大家詳細(xì)介紹了如何利用C#實(shí)現(xiàn)獲取當(dāng)前設(shè)備硬件信息的功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下2023-03-03
C#實(shí)現(xiàn)繪制鼠標(biāo)的示例代碼
這篇文章主要為大家詳細(xì)介紹了如何利用C#實(shí)現(xiàn)繪制鼠標(biāo)的效果,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)C#有一定的幫助,感興趣的小伙伴可以跟隨小編一起了解一下2022-12-12
VisualStudio2019安裝C#環(huán)境的實(shí)現(xiàn)方法
這篇文章主要介紹了VisualStudio2019安裝C#環(huán)境的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12
C#實(shí)現(xiàn)JSON和對象之間互相轉(zhuǎn)換功能示例
這篇文章主要介紹了C#實(shí)現(xiàn)JSON和對象之間互相轉(zhuǎn)換功能,結(jié)合實(shí)例形式較為詳細(xì)的分析了C#實(shí)現(xiàn)對象與json之間相互轉(zhuǎn)換的操作技巧,需要的朋友可以參考下2017-09-09

