了解Entity Framework中的事务

8

你好,我正在尝试使用Entity Framework进行事务处理。由于网上有很多关于实现事务的不同方式的信息,所以我有点困惑该如何选择正确的方式。我有一个示例数据库,其中包含两个表Employee和Company。Employee表具有指向公司ID的外键。考虑到我想要实现一个事务,在向Company表插入记录之后再向Employee表插入记录,并且只有在两者都成功插入时才插入记录,我有以下代码。

public void addCompanyToDatabase()
    {
        using (var context = new myTestEntities())
        {
            context.Connection.Open(); //added this as was getting the underlying   
            //provider failed to open
            using (TransactionScope scope = new TransactionScope())
            {
                try
                {
                    Company c = new Company();
                    c.Name = "xyz";
                    context.Companies.AddObject(c);
                    context.SaveChanges();

                    //int a = 0;
                    //int b = 5 / a;

                    Employee e = new Employee();
                    e.Age = 15;
                    e.Name = "James";
                    e.CompanyId = c.Id;
                    context.Employees.AddObject(e);
                    context.SaveChanges();

                    scope.Complete();
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Exception Occurred");
                }
            }
        }
    }

我想知道这是否是实现事务的正确方法。如果是,那么SaveChanges(false)scope.AcceptAllChanges()函数的作用是什么。任何信息都有帮助。

2个回答

14

在您的情况下,您无需管理任何连接或事务:Entity Framework会为您完成这项工作。当您没有提供一个已打开的连接(而是提供一个连接字符串)给EF时,在调用context.SaveChanges()期间,它将打开一个连接并启动一个事务。如果在那次调用过程中发生了错误,则事务将被回滚。

换句话说,您的方法可以简单地是这样:

public void addCompanyToDatabase()
{
    using (var context = new myTestEntities())
    {
        Company c = new Company();
        c.Name = "xyz";
        context.Companies.AddObject(c);

        Employee e = new Employee();
        e.Age = 15;
        e.Name = "James";
        e.CompanyId = c.Id;
        context.Employees.AddObject(e);

        // Only call SaveChanges last.
        context.SaveChanges();
    }
}

在我的例子中这样做很有意义。你可以给我一个需要事务的例子吗?如果上述代码是实现事务的正确方式吗?我猜使用两个不同上下文更新记录就是其中一种情况。 - nighthawk457
1
我遇到的最常见的需要使用事务的情况是,当您需要多次调用 SaveChanges 时。这可能发生在您需要新对象的(数据库生成的)ID或者需要强制ORM按照特定顺序执行操作时(例如,LINQ to SQL倾向于在插入之后重新排序删除,但这可能会触发数据库约束异常)。 - Steven
3
在所有情况下,仍然没有必要使用“TransactionScope”。如果您需要使用“TransactionScope”,因为您需要对多个数据库执行原子操作,则您的系统可能存在设计缺陷。我仅在自动化集成测试中使用“TransactionScope”。只需将调用代码包装在“TransactionScope”中,您就可以确保在测试结束时所有(数据库)更改都将被回滚,而无需更改任何代码。 - Steven

0

1-这个服务(我认为是事务服务)必须在客户端上运行,以支持TransactionScope。

2-当您的应用程序中有两个或更多个数据库,并且您希望所有数据库都进行事务更新(例如更改上下文的连接字符串)时,此功能非常有用。

3-当您有一个数据库时,最好使用SaveChanges(),它在内部实现了事务。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接