mysql ef6 事务_EF6中使用事务的方法总结

默认情况当你执行SaveChanges()的时候(insert update delete)来操作数据库时,Entity Framework会把这个操作包装在一个事务里,当操作结束后,事务也结束了。

EF6中的 Database.ExecuteSqlCommand()也会启用一个事务,事务的隔离级别是默认级别(Read Commited)。

虽然这种框架默认的事务处理机制对于大多数情况下已经够用了,但是是EF6为我们提供了API,让我们能够更加灵活地对自己代码中的事务进行控制。

一、在EF中使用事务

using System;

using System.Collections.Generic;

using System.Data.Entity;

using System.Data.SqlClient;

using System.linq;

using System.Transactions;

namespace TransactionsExamples

{

class TransactionsExample

{

static void StartOwnTransactionWithinContext()

{

using (var context = new BloggingContext())

{

using (var dbContextTransaction = context.Database.BeginTransaction())

{

try

{

context.Database.ExecuteSqlCommand(

@"UPDATE Blogs SET Rating = 5" +

" WHERE Name LIKE '%Entity Framework%'"

);

var query = context.Posts.Where(p => p.Blog.Rating >= 5);

foreach (var post in query)

{

post.Title += "[Cool Blog]";

}

context.SaveChanges();

dbContextTransaction.Commit();

}

catch (Exception)

{

dbContextTransaction.Rollback();

}

}

}

}

}

}

上面通过一个using语句块把要使用事务的操作起来,调用context.Database.BeginTransaction()启动一个事务,最后分别通过dbContextTransaction.Commit();和dbContextTransaction.Rollback();来提交或回滚事务。

注意:开启一个事务需要事务所有在的数据库链接是打开的,因此当所在数据库链接没有打开时Database.BeginTransaction()就会打开一个数据库链接。上面调用context.Database.BeginTransaction()是没有参数的,你可以调用这个BeginTransaction()其它重载函数来控制事务的隔离级别,如果没传参数将会使用默认的隔离级别。

二、传递一个已存在的事务

EF中可以传递一个存在的事务给context:

using System;

using System.Collections.Generic;

using System.Data.Entity;

using System.Data.SqlClient;

using System.Linq;

sing System.Transactions;

namespace TransactionsExamples

{

class TransactionsExample

{

static void UsingExternalTransaction()

{

using (var conn = new SqlConnection("..."))

{

conn.Open();

using (var sqlTxn = conn.BeginTransaction(System.Data.IsolationLevel.Snapshot))

{

try

{

var sqlCommand = new SqlCommand();

sqlCommand.Connection = conn;

sqlCommand.Transaction = sqlTxn;

sqlCommand.CommandText =

@"UPDATE Blogs SET Rating = 5" +

" WHERE Name LIKE '%Entity Framework%'";

sqlCommand.ExecuteNonQuery();

using (var context =

new BloggingContext(conn, contextOwnsConnection: false))

{

context.Database.UseTransaction(sqlTxn);

var query = context.Posts.Where(p => p.Blog.Rating >= 5);

foreach (var post in query)

{

post.Title += "[Cool Blog]";

}

context.SaveChanges();

}

sqlTxn.Commit();

}

catch (Exception)

{

sqlTxn.Rollback();

}

}

}

}

}

}

三、TransactionScope事务

EF中让多个数据库操作作为一个整体的事务来处理除了上面使用事务传递来实现外,还可以利用TransactionScope对象来处理,如下:

using System.Collections.Generic;

using System.Data.Entity;

using System.Data.SqlClient;

using System.Linq;

using System.Transactions;

namespace TransactionsExamples

{

class TransactionsExample

{

static void UsingTransactionScope()

{

using (var scope = new TransactionScope(TransactionScopeOption.Required))

{

using (var conn = new SqlConnection("..."))

{

conn.Open();

var sqlCommand = new SqlCommand();

sqlCommand.Connection = conn;

sqlCommand.CommandText =

@"UPDATE Blogs SET Rating = 5" +

" WHERE Name LIKE '%Entity Framework%'";

sqlCommand.ExecuteNonQuery();

using (var context =

new BloggingContext(conn, contextOwnsConnection: false))

{

var query = context.Posts.Where(p => p.Blog.Rating > 5);

foreach (var post in query)

{

post.Title += "[Cool Blog]";

}

context.SaveChanges();

}

}

scope.Complete();

}

}

}

}

注意:上面提交事务是通过TransactionScope实例的Complete方法来提交的。

可以看到使用TransactionScope使我们代码简化了不少,但是要注意的是TransactionScope也有一些限制:

1、需要NET 4.5.1及以上

2、不能和Database.UseTransaction()方式结合起来使用

3、sql语句中不能有DLL操作

4、不能在云场景中使用,除非你保证只有一个数据库连接。(支场景中不支持分布式事务)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值