实体框架:带有标识列的插入“有时”失败,带有OptimisticConcurrencyException

时间:2009-11-11 15:57:56

标签: .net entity-framework exception

开发中&使用Entity Framework学习,当我在模型中运行一个实体的测试时,我对插入有一个奇怪的问题。具体来说,问题是在一起运行一些测试时。我会自己解释一下:

我的模型中有一个名为“DtoCategoria”的实体,有2个成员:id:Int32和name:string,映射到一个表,其中id是一个标识列。这很好,很简单。

我有一个名为CadCategoria的DTO数据访问层,我在这里创建了一个插入方法,如:

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);
    }
}

现在出现了一个额外的事情:

  • 单独运行更新测试时:已通过测试
  • 运行更新&添加测试:通过测试
  • 运行更新&删除测试:更新测试失败并删除已通过!

错误发生在测试的第二行:bd.add(a);这会在上下文的SaveChanges方法中引发OptimisticConcurrencyException。

知道为什么我有一个带有标识列的插入的并发异常?并且只有与删除测试方法结合使用?当与add测试结合使用时,它也不会发生,也会执行“添加”操作??

我担心如果测试失败,它也可能在真正的应用程序中失败。对于没有标识列ID为PK的其他DTO,不会发生这种情况。

有什么想法吗?非常感谢!!!

塞吉

1 个答案:

答案 0 :(得分:0)

嗯,我想我终于找到了这个问题。它与Singleton模式无关。事实是我的删除测试试图删除不存在的对象,只是为了检查方法是否返回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;
        }
    }

解决方案是catch部分中的bd.Detach(entity);命令,告诉上下文忘记这个模拟实体。快速浏览SQL profiler给了我答案。

这就是为什么订单很重要:删除然后更新导致更新崩溃。保留删除作为最后一个,工作正常,因为没有更多的SaveChanges()到上下文。

感谢您的病人@Craig,并对给您带来的不便表示抱歉。

塞吉。