自实体加载后,实体可能已被修改或删除。交易期间出错

时间:2016-03-20 20:13:15

标签: entity-framework dbcontext

在执行以下代码时,我收到消息

  

存储更新,插入或删除语句会影响意外的行数(0)。自实体加载后,实体可能已被修改或删除。刷新ObjectStateManager条目。

这里有很多事情发生,但我找不到解决问题的方法。

这只发生在我身上,因为我在一个事务中运行_db.SaveChanges()两次(_db是我的数据库上下文对象),我必须这样做,因为我需要生成的ID才能给我以继续代码。

如果有人可以帮助我,我会很感激。此外,如果您知道如何在没有两个_db.SaveChanges()的情况下继续进行,或者采用不同的方式来处理交易,我欢迎您展示它。

using (var trans = _db.Database.BeginTransaction())
{
    try
    {
        var f = cbxFornecedor.SelectedItem as Fornecedor;
        var c = new Compra
                {
                    CompraId = compra.CompraId,
                    DataCompra = dtpDataCompra.Value,
                    ListaProdutos = new List<ListaProdutos>(),
                    Fornecedor = f,
                    Referencia = tbxReferencia.Text,
                    Situacao = rbtEntregue.Checked
                };

        _db.Compras.Add(c);
        _db.SaveChanges();

        foreach (var cada in _itens)
            c.ListaProdutos.Add(new ListaProdutos
                    {
                        Compra = c,
                        CompraId = c.CompraId,
                        Produto = cada.ProdutoClasse,
                        ProdutoId = cada.ProdutoClasse.ProdutoId,
                        Valor = cada.ValorTotal,
                        Quantidade = cada.Quantidade,
                    });

        foreach (var cada in c.ListaProdutos)
            if (_db.ListaProdutos.Find(cada.CompraId, cada.ProdutoId) != null)
                _db.Entry(cada).State = EntityState.Modified;
            else
                _db.ListaProdutos.Add(cada);

        _db.Entry(c).State = EntityState.Modified;
        _db.SaveChanges();

        trans.Commit();
    }
    catch (Exception ex)
    {
        trans.Rollback();
        MessageBox.Show(this, ex.Message, @"Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

而且,为了清楚起见,我知道我的问题在于交易存在的事实。我尝试删除它,它工作。另外,如果我拿出第二个_db.SaveChanges(),它也可以。

仅在第二个_db.SaveChanges()中抛出异常,并且只有在它被事务块包围时才会抛出异常。

1 个答案:

答案 0 :(得分:0)

这不是您问题的直接答案,但可能会有所帮助。

您无需为new ListaProdutos指定Compra和CompraId,因为EF非常聪明,可以解决问题。此外,您似乎不需要_db.ListaProdutos.Find(cada.CompraId, cada.ProdutoId) != null检查,因为cada.CompraId - 是新ID,此时它不能在DB中。此外,您不需要_db.ListaProdutos.Add(cada);因为EF已经是新的,您正在添加此记录。你能试试下一个代码吗?

var f = cbxFornecedor.SelectedItem as Fornecedor;
var c = new Compra
    {
        DataCompra = dtpDataCompra.Value,
        ListaProdutos = new List<ListaProdutos>(),
        Fornecedor = f,
        Referencia = tbxReferencia.Text,
        Situacao = rbtEntregue.Checked
    };

_db.Compras.Add(c); 

foreach (var cada in _itens)
    c.ListaProdutos.Add(new ListaProdutos
        {
            Produto = cada.ProdutoClasse,
            ProdutoId = cada.ProdutoClasse.ProdutoId,
            Valor = cada.ValorTotal,
            Quantidade = cada.Quantidade,
        });
_db.SaveChanges();