什么';s具有单个和多个SaveChanges()调用的Entity Framework(6)事务之间的区别

本文关键字:调用 Entity Framework 区别 之间 事务 SaveChanges 单个 什么 | 更新日期: 2023-09-27 18:26:48

我想知道在同一数据库上下文中执行事务的实际区别是什么:

1) 一个SaveChanges()的多个操作,而不显式使用sql事务

using (TestDbContext db = new TestDbContext())
{
    // first operation
    // second operation
    db.SaveChanges();
}

2) 使用sql事务的单个SaveChanges()的多个操作

using (TestDbContext db = new TestDbContext())
using (DbContextTransaction trans = db.Database.BeginTransaction())
{
     // operation 1
     // operation 2
     db.SaveChanges();    
     trans.commit();
}

3) 使用sql事务的多个SaveChanges()的多个操作

using (TestDbContext db = new TestDbContext())
using (DbContextTransaction trans = db.BeginTransaction())
{
     // operation 1
     db.SaveChanges();    
     // operation 2
     db.SaveChanges();
     trans.commit();
}

在(2)和(3)中,如果假设commit()实际执行对数据库的请求sql查询,那么它真的不同吗?比如说,为每个操作保存更改,还是同时为所有操作保存更改?

如果(1)也可以允许在同一数据库上下文中安全地执行多个操作,那么手动启动事务的主要用途是什么?我想说,如果发生不好的事情,我们可以手动提供try/catch块来回滚事务,但AFAIK,SaveChanges()也会自动覆盖它,至少在SQLServer中是这样。

**更新:另一件事是:我应该将数据库上下文和事务变量设置为类级别,还是这些变量应该是仅包含方法的本地变量?

什么';s具有单个和多个SaveChanges()调用的Entity Framework(6)事务之间的区别

如果不启动事务,它是隐式的。也就是说,您执行的所有SaveChanges()都将在呼叫后立即在数据库中可用。

如果启动事务,SaveChanges()仍然执行更新,但在调用commit之前,其他连接无法使用数据。

您可以通过设置断点、创建新对象、将它们添加到上下文中以及执行SaveChanges()来自己测试这一点。您将看到ID属性在调用后将有一个值,但在对事务执行提交之前,数据库中不会有相应的行。

至于第二个问题,它实际上取决于并发需求、类在做什么以及处理了多少数据。与其说是范围界定问题,不如说是代码执行问题。

上下文不是线程安全的,所以只要应用程序中只有一个线程访问上下文,就可以在更大的范围内进行访问。但是,如果应用程序的其他实例正在访问数据,则必须确保将数据刷新为最新模型。您还应该考虑到,随着时间的推移,加载到内存中的模型越多,保存速度就越慢。

我倾向于创建尽可能接近要执行的操作的上下文,并在之后不久处理它们。

您的问题似乎根本不是关于实体框架,而是关于sql事务。sql事务是单个"原子"更改。也就是说,要么所有的更改都已提交,要么没有提交。

你并没有一个真正涵盖这个场景的例子,但如果你添加了另一个例子,比如:

using (TestDbContext db = new TestDbContext())
{
     // operation 1
     db.SaveChanges();    
     // operation 2
     db.SaveChanges();
}

在本例中,如果第一个操作保存成功,但第二个操作失败,则可能出现第一步提交的数据可能无效的情况。

这就是为什么您要使用sql事务,将两个SaveChanges封装到一个操作中,这意味着所有数据都被提交,或者没有被提交。