[英]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.