如何在Entity Framework6中使用合并交易
How to use combined transactions in Entity Framework 6
我有两个 class。第一个代表主数据,第二个代表其详细数据(它们通过外键连接)。
由于详细记录需要现有的主记录,因此我必须先保存主记录。不幸的是,在保存细节数据的过程中可能会发生错误,所以我也应该回滚主数据的保存以防出错。
我有以下代码。
硕士class:
MyDataContext db=new MyDataContext();
DetailData detail=new DetailData();
using (var transaction= db.Database.BeginTransaction())
{
try
{
//db.Database.CommandTimeout = 10;
db.SaveChanges();
//saving details
detail.SaveData(masterId);
//on success
transaction.Commit();
}
catch (Exception)
{
transaction.Rollback();
throw;
}
}
详情class:
MyDataContext db;
DataItem dataItem;
public DetailData()
{
db=new MyDataContext();
dataItem=new DataItem();
db.DataItem.Attach(dataItem);
}
public SaveData(int id)
{
dataItem.Master_ID=id;
db.SaveChanges();
}
由于 best practice by Microsoft 按需使用 DataContext,我不想将现有上下文传递到详细数据中。
In general, a DataContext instance is designed to last for one "unit
of work" however your application defines that term. A DataContext is
lightweight and is not expensive to create. A typical LINQ to SQL
application creates DataContext instances at method scope or as a
member of short-lived classes that represent a logical set of related
database operations.
不幸的是,我得到一个超时异常,因为主事务尚未提交,我在不同的上下文对象上启动了一个新的SaveChanges
。
如果我使用 db.DataBase.UseTransaction
并传递 master class 的事务,我会得到另一个关于事务 属于另一个上下文 的异常。
那么如何将主数据和明细数据的保存合并到一个工作事务中呢?
也许我误解了你的问题,或者下面的模式在你的情况下是不可能的,但通常你可以像这样添加 master/detail 条记录:
var customer = new Customer();
dbContext.Customers.Add(customer);
var order = new Order();
order.Customer = customer;
dbContext.SaveChanges();
这假设您的 Customer
和 Order
表与外键链接,并具有合适的 EF 导航属性(例如 order.Customer
)。
Entity Framework 将以正确的顺序添加 Customer
和 Order
记录,并添加到事务内的整个更新中,因此两个更新都成功,或者都不成功。
UPDATE:如果您有两个上下文,每个上下文都不会意识到另一个所做的更改 - 如果您尝试将一个对象从一个上下文添加到另一个上下文,你会得到错误。
我怀疑你得到的超时是因为每个上下文都试图在一个事务中执行一些数据库操作,而第一个事务阻塞了第二个。这并不表示您应该 "combine" 上下文 - 它表示您应该只有一个上下文。
您添加到问题中的引文谈到了工作单元。您的工作单元在逻辑上应该包括您对主记录和详细记录所做的所有更改。这就是重点。 您应该只有一个上下文! :-) 但是,您可以在该上下文内创建一个事务。
如果我没理解错的话,你的 Master class 正在尝试做两项工作:表示主数据记录并管理其持久性。细节同上 class。这样违背了Separation of Concerns的原则,很可能会抛出这样的问题。
使用存储库和工作单元模式将帮助您将实体与管理事务的逻辑分开。请参阅 Tom Dykstra's excellent tutorial 关于 MVC 中的存储库和工作单元模式。
我有两个 class。第一个代表主数据,第二个代表其详细数据(它们通过外键连接)。 由于详细记录需要现有的主记录,因此我必须先保存主记录。不幸的是,在保存细节数据的过程中可能会发生错误,所以我也应该回滚主数据的保存以防出错。
我有以下代码。
硕士class:
MyDataContext db=new MyDataContext();
DetailData detail=new DetailData();
using (var transaction= db.Database.BeginTransaction())
{
try
{
//db.Database.CommandTimeout = 10;
db.SaveChanges();
//saving details
detail.SaveData(masterId);
//on success
transaction.Commit();
}
catch (Exception)
{
transaction.Rollback();
throw;
}
}
详情class:
MyDataContext db;
DataItem dataItem;
public DetailData()
{
db=new MyDataContext();
dataItem=new DataItem();
db.DataItem.Attach(dataItem);
}
public SaveData(int id)
{
dataItem.Master_ID=id;
db.SaveChanges();
}
由于 best practice by Microsoft 按需使用 DataContext,我不想将现有上下文传递到详细数据中。
In general, a DataContext instance is designed to last for one "unit of work" however your application defines that term. A DataContext is lightweight and is not expensive to create. A typical LINQ to SQL application creates DataContext instances at method scope or as a member of short-lived classes that represent a logical set of related database operations.
不幸的是,我得到一个超时异常,因为主事务尚未提交,我在不同的上下文对象上启动了一个新的SaveChanges
。
如果我使用 db.DataBase.UseTransaction
并传递 master class 的事务,我会得到另一个关于事务 属于另一个上下文 的异常。
那么如何将主数据和明细数据的保存合并到一个工作事务中呢?
也许我误解了你的问题,或者下面的模式在你的情况下是不可能的,但通常你可以像这样添加 master/detail 条记录:
var customer = new Customer();
dbContext.Customers.Add(customer);
var order = new Order();
order.Customer = customer;
dbContext.SaveChanges();
这假设您的 Customer
和 Order
表与外键链接,并具有合适的 EF 导航属性(例如 order.Customer
)。
Entity Framework 将以正确的顺序添加 Customer
和 Order
记录,并添加到事务内的整个更新中,因此两个更新都成功,或者都不成功。
UPDATE:如果您有两个上下文,每个上下文都不会意识到另一个所做的更改 - 如果您尝试将一个对象从一个上下文添加到另一个上下文,你会得到错误。
我怀疑你得到的超时是因为每个上下文都试图在一个事务中执行一些数据库操作,而第一个事务阻塞了第二个。这并不表示您应该 "combine" 上下文 - 它表示您应该只有一个上下文。
您添加到问题中的引文谈到了工作单元。您的工作单元在逻辑上应该包括您对主记录和详细记录所做的所有更改。这就是重点。 您应该只有一个上下文! :-) 但是,您可以在该上下文内创建一个事务。
如果我没理解错的话,你的 Master class 正在尝试做两项工作:表示主数据记录并管理其持久性。细节同上 class。这样违背了Separation of Concerns的原则,很可能会抛出这样的问题。
使用存储库和工作单元模式将帮助您将实体与管理事务的逻辑分开。请参阅 Tom Dykstra's excellent tutorial 关于 MVC 中的存储库和工作单元模式。