.net 实体框架:插入标识列失败";有时";带着乐观的心情
在使用实体框架进行开发和学习时,当我为模型中的一个实体运行测试时,我在插入方面遇到了一个奇怪的问题。具体来说,问题是在一起运行一些测试时。我会解释我自己: 我的模型中有一个名为“DtoCategoria”的实体,有两个成员:id:Int32和name:string,映射到一个表中,其中id是一个标识列。这很好,也很简单 我有一个用于此DTO的数据访问层,称为CadCategoria,我在其中创建了一个用于进行插入的方法,如:.net 实体框架:插入标识列失败";有时";带着乐观的心情,.net,entity-framework,exception,.net,Entity Framework,Exception,在使用实体框架进行开发和学习时,当我为模型中的一个实体运行测试时,我在插入方面遇到了一个奇怪的问题。具体来说,问题是在一起运行一些测试时。我会解释我自己: 我的模型中有一个名为“DtoCategoria”的实体,有两个成员:id:Int32和name:string,映射到一个表中,其中id是一个标识列。这很好,也很简单 我有一个用于此DTO的数据访问层,称为CadCategoria,我在其中创建了一个用于进行插入的方法,如: public class CadCategoria { pro
public class CadCategoria
{
protected readonly CUENTASEntities bd = Singletons.bd;
public bool add(EntityObject entity)
{
try
{
bd.AddObject(EntitySet, entity);
return bd.SaveChanges() > 0;
}
catch (Exception e)
{
bd.Detach(entity);
return false;
}
}
// and some other methods... update, delete, etc.
}
以及其他一些用于更新和删除的通用方法。我通过应用程序中的层以单例模式共享上下文,如下所示:
public class Singletons
{
public static CUENTASEntities bd;
static Singletons()
{
bd = new CUENTASEntities();
}
}
从现在起这看起来很好。但是,我创建了一些单元测试,以查看是否一切正常,如下所示:
[TestClass]
public class CadCategoriaTest
{
private CadCategoria bd = new CadCategoria();
[TestMethod]
public void addTest()
{
var catAdd = new DtoCategoria { name= "cat 1" };
Assert.IsTrue(bd.add(catAdd));
bd.delete(catAdd);
}
[TestMethod]
public void deleteTest()
{
var catDel = new DtoCategoria { name= "cat 2" };
bd.add(catDel);
Assert.IsTrue(bd.delete(catDel));
Assert.IsFalse(bd.delete(new DtoCategoria { name= "not exists", id = -1 }));
}
[TestMethod]
public void updateTest()
{
var a = new DtoCategoria { name= "cat 3" };
bd.add(a);
a.nombre = "name modified";
Assert.IsTrue(bd.update(a));
var b = bd.get(-1);
Assert.IsFalse(bd.update(b));
bd.delete(a);
}
}
现在是外星人的事情:
- 单独运行更新测试时:测试通过
- 运行更新和添加测试时:测试通过
- 运行更新和删除测试时:更新测试失败,删除通过李>
塞尔吉嗯,我想我终于找到了问题所在。这与单身模式无关。事实上,我的delete测试尝试删除不存在的对象,只是为了检查该方法是否返回false:
Assert.IsFalse(bd.delete(new DtoCategoria { name= "not exists", id = -1 }));
但是在bd.delete方法中,我忘了将不存在的对象从上下文中分离,所以下次我尝试执行context.SaveChanges()时,再次删除错误的对象是很困难的,因此它再次引发OptimisticException,因为没有删除的行
这是我的bd.delete方法:
public bool delete(EntityObject entity)
{
try
{
if (entity.EntityKey == null)
entity.EntityKey = bd.CreateEntityKey(EntitySet, entity);
if (entity.EntityState == EntityState.Detached)
bd.AttachTo(EntitySet, entity);
bd.DeleteObject(entity);
return bd.SaveChanges() > 0;
}
catch (Exception e)
{
bd.Detach(entity);
return false;
}
}
解决方案是bd.Detach(实体)命令,告诉上下文忽略此模拟实体。快速浏览一下SQL分析器,我就知道了答案
这就是为什么顺序很重要:删除然后更新导致更新崩溃。保留delete作为最后一个,效果很好,因为上下文中不再有SaveChanges()
谢谢你的耐心,@Craig,很抱歉给你带来不便
Sergi。将ObjectContext设置为单例几乎肯定会导致问题。我不确定它是否会导致这个问题,但我不会费心去解决这个问题,直到你摆脱单身,因为当你这样做的时候问题可能会消失。此外,使用异常几乎总是错误的,可能会掩盖实际问题。我继续测试,发现测试的运行顺序很重要:删除和更新失败,但更新和删除通过。。。。知道吗?我忘了说我正在开发一个windows应用程序,它是单线程的,并且测试运行时可能是多线程的?如果是这样,这可能是问题所在,因为关于MSDN:“ObjectContext类不是线程安全的。ObjectContext中的数据对象的完整性在多线程场景中无法保证。”这可能是原因吗?Thanx Craig,但Singleton对我来说运行良好,因为我每个实体有一个DAL类,共享上下文,因为实体与其他实体相互关联,并且具有多个上下文会导致应用程序失败,且不一致。不要使用多个上下文或单个上下文。相反,在应用程序中适当地管理上下文生命周期。你不能跳过这个!