zoukankan      html  css  js  c++  java
  • EF6中使用事务的方法

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

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

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

    一、在EF中使用事务

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Data.Entity;
    4. using System.Data.SqlClient;
    5. using System.linq;
    6. using System.Transactions;
    7. namespace TransactionsExamples
    8. {
    9. class TransactionsExample
    10. {
    11. static void StartOwnTransactionWithinContext()
    12. {
    13. using (var context = new BloggingContext())
    14. {
    15. using (var dbContextTransaction = context.Database.BeginTransaction())
    16. {
    17. try
    18. {
    19. context.Database.ExecuteSqlCommand(
    20. @"UPDATE Blogs SET Rating = 5" +
    21. " WHERE Name LIKE '%Entity Framework%'"
    22. );
    23. var query = context.Posts.Where(p => p.Blog.Rating >= 5);
    24. foreach (var post in query)
    25. {
    26. post.Title += "[Cool Blog]";
    27. }
    28. context.SaveChanges();
    29. dbContextTransaction.Commit();
    30. }
    31. catch (Exception)
    32. {
    33. dbContextTransaction.Rollback();
    34. }
    35. }
    36. }
    37. }
    38. }
    39. }

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

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

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

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

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Data.Entity;
    4. using System.Data.SqlClient;
    5. using System.Linq;
    6. sing System.Transactions;
    7. namespace TransactionsExamples
    8. {
    9. class TransactionsExample
    10. {
    11. static void UsingExternalTransaction()
    12. {
    13. using (var conn = new SqlConnection("..."))
    14. {
    15. conn.Open();
    16. using (var sqlTxn = conn.BeginTransaction(System.Data.IsolationLevel.Snapshot))
    17. {
    18. try
    19. {
    20. var sqlCommand = new SqlCommand();
    21. sqlCommand.Connection = conn;
    22. sqlCommand.Transaction = sqlTxn;
    23. sqlCommand.CommandText =
    24. @"UPDATE Blogs SET Rating = 5" +
    25. " WHERE Name LIKE '%Entity Framework%'";
    26. sqlCommand.ExecuteNonQuery();
    27. using (var context =
    28. new BloggingContext(conn, contextOwnsConnection: false))
    29. {
    30. context.Database.UseTransaction(sqlTxn);
    31. var query = context.Posts.Where(p => p.Blog.Rating >= 5);
    32. foreach (var post in query)
    33. {
    34. post.Title += "[Cool Blog]";
    35. }
    36. context.SaveChanges();
    37. }
    38. sqlTxn.Commit();
    39. }
    40. catch (Exception)
    41. {
    42. sqlTxn.Rollback();
    43. }
    44. }
    45. }
    46. }
    47. }
    48. }

      

    三、TransactionScope事务

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

    1. using System.Collections.Generic;
    2. using System.Data.Entity;
    3. using System.Data.SqlClient;
    4. using System.Linq;
    5. using System.Transactions;
    6. namespace TransactionsExamples
    7. {
    8. class TransactionsExample
    9. {
    10. static void UsingTransactionScope()
    11. {
    12. using (var scope = new TransactionScope(TransactionScopeOption.Required))
    13. {
    14. using (var conn = new SqlConnection("..."))
    15. {
    16. conn.Open();
    17. var sqlCommand = new SqlCommand();
    18. sqlCommand.Connection = conn;
    19. sqlCommand.CommandText =
    20. @"UPDATE Blogs SET Rating = 5" +
    21. " WHERE Name LIKE '%Entity Framework%'";
    22. sqlCommand.ExecuteNonQuery();
    23. using (var context =
    24. new BloggingContext(conn, contextOwnsConnection: false))
    25. {
    26. var query = context.Posts.Where(p => p.Blog.Rating > 5);
    27. foreach (var post in query)
    28. {
    29. post.Title += "[Cool Blog]";
    30. }
    31. context.SaveChanges();
    32. }
    33. }
    34. scope.Complete();
    35. }
    36. }
    37. }
    38. }

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

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

    1、需要NET 4.5.1及以上

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

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

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

  • 相关阅读:
    洛谷1026 统计单词个数
    洛谷1381 单词背诵
    Manacher(hdu3068最长回文)
    洛谷P1078 文化之旅
    HDU1269 迷宫城堡
    codevs1020 孪生蜘蛛
    洛谷P1027 Car的旅行路线
    楼房 洛谷1382 && codevs2995
    Picture poj1177
    排列组合
  • 原文地址:https://www.cnblogs.com/pressforward/p/7601314.html
Copyright © 2011-2022 走看看