Entity Framework 4.1乱抛EntitySqlException的BUG
罗朝辉 (http://kesalin.cnblogs.com/)
今天在使用 Entity Framework 处理并发冲突时,碰到一个奇怪的BUG:
引发 BUG 的代码:
try
{
if (ModelState.IsValid)
{
db.Entry(entityObject).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
}
catch (DbUpdateConcurrencyException ex)
{
var entry = ex.Entries.Single();
var databaseValues = (XXXProject.Models.XXXEntity)entry.GetDatabaseValues().ToObject();
var clientValues = ( XXXProject .Models. XXXEntity )entry.Entity;
......
}
BUG现象:
EntitySqlException: Type 'XXXProject.Models.XXXEntity' could not be found. Make sure that the required schemas are loaded and that the namespaces are imported correctly.
BUG原因:
DBContext 实例和 Model entity 不在同一个命名空间下,Entity Framework 4.1 中的 GetDatabaseValues()就会抛出异常。经查证,这是 Entity Framework 4.1 的一个BUG,详细讨论请参看:这里。
解决方案之一:
var clientValues = (Department)entry.CurrentValues.Clone().ToObject();
entry.Reload();
var databaseValues = (Department)entry.CurrentValues.ToObject();
这样就避开了对 GetDatabaseValues()的调用,而同时能获取到客户端的值以及服务器端的值。唯一要注意的是 entry 已经重新 Reload 了,之前客户端做出的修改如果想要保持就得在 Reload 之前备份。
解决方案之二:
将 DBContext 实例和 Model entity 放到同一个命名空间下,这样就满足 GetDatabaseValues() 的约束条件了。
不推荐使用这种方案,因为这样修改代码较多,且违背分层隔离原则。