繁体   English   中英

如何在Date Entity Framework中回滚事务

[英]How to rollback a transaction in Date Entity Framework

我正在尝试使用数据实体框架创建我的数据访问层。 在到目前为止的工作中,我使用了ADO.Net。 我正在努力弄清事务在EF中的工作方式。 我读了很多书,但是它比以前让我更加困惑! 我通常会做一些思考(例如简化):

using (SqlConnection conn = new SqlConnection(_connString))
{
    using (SqlTransaction trans = conn.BeginTransaction())
    {
        try
        {
            using (SqlCommand cmd = new SqlCommand("usp_CreateNewInvoice", conn))
            {
                cmd.Transaction = trans;
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.Add(new SqlParameter("@InvoiceName", Invoice.invoicename));
                 cmd.Parameters.Add(new SqlParameter("@InvoiceAddess", Invoice.invoiceaddress));
                 _invoiceid = Convert.ToInt32(cmd.ExecuteScalar());
            }
            foreach (InvoiceLine inLine in Invoice.Lines)
            {
                using (SqlCommand cmd = new SqlCommand("usp_InsertInvoiceLines", conn))
                {
                    cmd.Transaction = trans;
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Parameters.Add(new SqlParameter("@InvNo", _invoiceid));
                    cmd.Parameters.Add(new SqlParameter("@InvLineQty", inLine.lineqty));
                    cmd.Parameters.Add(new SqlParameter("@InvLineGrossPrice", inLine.linegrossprice));
                    cmd.ExecuteNonQuery();
                }
            }
            trans.Commit();
        }
        catch (SqlException sqlError)
        {
            trans.Rollback();
        }
    }
}

现在我想在EF中做同样的事情:

        using (TransactionScope scope = new TransactionScope())
        {
            try
            {
                var DbContext = new CCTStoreEntities();

                CCTInvoice invHead = new CCTInvoice();
                invHead.Name = Invoice.invoicename;
                invHead.Address = Invoice.invoiceaddress;

                DbContext.CCTInvoices.Add(invHead);
                DbContext.SaveChanges(false);
                _iid = invHead.InvoiceId;

                foreach (InvoiceLine inLine in Invoice.Lines)
                {
                    CCTInvoiceLine invLine = new CCTInvoiceLine();
                    invLine.InvoiceNo = _iid;
                    invLine.Quantity = inLine.lineqty;
                    invLine.GrossPrice = inLine.linegrossprice;
                    DbContext.CCTInvoiceLines.Add(invHead);
                    DbContext.SaveChanges(false);
                }

                DbContext.SaveChanges();
                scope.Complete();

            }
            catch
            {
                //Something went wrong
                //Rollback!
            }
        }

从我读到的SaveChanges(false)表示将继续跟踪所做的更改。 但是,如果出现问题,我该如何回滚事务?

TransactionScope的回滚机制是隐式的。

基本上,如果在TransactionScope之前不调用Complete ,它将自动回滚。 请参阅“ 使用事务范围实现隐式事务”中“回滚事务”部分。

因此,从技术上讲,您甚至不需要在此处使用try...catch (除非您想执行其他操作,例如记录日志)。

您无需在catch块上执行任何操作。 只需不调用DbContext.SaveChanges ,就不DbContext.SaveChanges任何更改发送到数据库,并且一旦处理DbContext,更改将丢失。

你确实有问题。 必须正确地将DbContext包装在using块上,如下所示。 顺便说一句,我不认为DbContext.SaveChanges(false); 需要时,您的代码应仅与最终的DbContext.SaveChanges(); EF将负责连接所有外键,因此您无需明确地进行此操作。

    using (TransactionScope scope = new TransactionScope())
    {
        try
        {
            using (var DbContext = new CCTStoreEntities())
            {
                CCTInvoice invHead = new CCTInvoice();
                invHead.Name = Invoice.invoicename;
                invHead.Address = Invoice.invoiceaddress;

                DbContext.CCTInvoices.Add(invHead);
                DbContext.SaveChanges(false); // This is not needed
                _iid = invHead.InvoiceId;     // This is not needed

                foreach (InvoiceLine inLine in Invoice.Lines)
                {
                    CCTInvoiceLine invLine = new CCTInvoiceLine();
                    invLine.InvoiceNo = _iid; // This is not needed
                    invLine.Quantity = inLine.lineqty;
                    invLine.GrossPrice = inLine.linegrossprice;
                    DbContext.CCTInvoiceLines.Add(invHead);
                    DbContext.SaveChanges(false); // This is not needed
                }

                DbContext.SaveChanges();
                scope.Complete();
            }
        }
        catch
        {
            //Something went wrong
            //Rollback!
        }
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM