.net core 实例教程(八)事务提交配置、TransactionScope使用

本文源码下载地址:http://www.80cxy.com/Blog/ResourceView?arId=202403191532545995NAAqJh

系列教程地址:http://www.80cxy.com/Blog/ArticleView?arId=202403191517574161ay3s5V

.net core 实例教程(三)仓储及领域服务功能实现(既实现用户表的增删改查接口)文章中讲解了数据库增删改查基本操作,数据库保存是在仓储代码中实现的。也没使用事务提交。本文讲解利用IAsyncActionFilter过滤器统计进行事务提交配置。

1

2

3

4

5

6

7

public async Task<SysUser> AddUser(string userName, string password, string realName, string userType)

{

    SysUser model = SysUser.Add(userName, password, realName, userType);

    await _dbContext.SysUser.AddAsync(model);

    await _dbContext.SaveChangesAsync();

    return model;

}

一、UnitOfWorkFilter实现代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

using Microsoft.AspNetCore.Mvc.Abstractions;

using Microsoft.AspNetCore.Mvc.Controllers;

using Microsoft.AspNetCore.Mvc.Filters;

using Microsoft.EntityFrameworkCore;

using Microsoft.Extensions.DependencyInjection;

using System.Reflection;

using System.Transactions;

namespace SignUp.Common.ASPNETCore

{

    public class UnitOfWorkFilter : IAsyncActionFilter

    {

        private static UnitOfWorkAttribute? GetUoWAttr(ActionDescriptor actionDesc)

        {

            var caDesc = actionDesc as ControllerActionDescriptor;

            if (caDesc == null)

            {

                return null;

            }

            //try to get UnitOfWorkAttribute from controller,

            //if there is no UnitOfWorkAttribute on controller,

            //try to get UnitOfWorkAttribute from action

            var uowAttr = caDesc.ControllerTypeInfo

                .GetCustomAttribute<UnitOfWorkAttribute>();

            //方法标注UnitOfWorkAttribute,进行事务控制

            if (uowAttr != null)

            {

                return uowAttr;

            }

            else

            {

                return caDesc.MethodInfo

                    .GetCustomAttribute<UnitOfWorkAttribute>();

            }

        }

        public async Task OnActionExecutionAsync(ActionExecutingContext context,

            ActionExecutionDelegate next)

        {

            var uowAttr = GetUoWAttr(context.ActionDescriptor);

            if (uowAttr == null)

            {

                await next();

                return;

            }

            using TransactionScope txScope = new(TransactionScopeAsyncFlowOption.Enabled);

            List<DbContext> dbCtxs = new List<DbContext>();

            foreach (var dbCtxType in uowAttr.DbContextTypes)

            {

                //用HttpContext的RequestServices

                //确保获取的是和请求相关的Scope实例

                var sp = context.HttpContext.RequestServices;

                DbContext dbCtx = (DbContext)sp.GetRequiredService(dbCtxType);

                dbCtxs.Add(dbCtx);

            }

            var result = await next();

            if (result.Exception == null)

            {

                foreach (var dbCtx in dbCtxs)

                {

                    await dbCtx.SaveChangesAsync();

                }

                txScope.Complete();

            }

        }

    }

}

using Microsoft.EntityFrameworkCore;

namespace SignUp.Common.ASPNETCore

{

    [AttributeUsage(AttributeTargets.Class

    | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]

    public class UnitOfWorkAttribute : Attribute

    {

        public Type[] DbContextTypes { get; init; }

        public UnitOfWorkAttribute(params Type[] dbContextTypes)

        {

            this.DbContextTypes = dbContextTypes;

            foreach (var type in dbContextTypes)

            {

                if (!typeof(DbContext).IsAssignableFrom(type))

                {

                    throw new ArgumentException($"{type} must inherit from DbContext");

                }

            }

        }

    }

}

二、使用方法

在需要事务提交的控制器或action上使用[UnitOfWork(typeof(SignUpDbContext))]特性即可。然后将仓储保存代码删除。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

using Microsoft.AspNetCore.Http;

using Microsoft.AspNetCore.Mvc;

using SignUp.Common.ASPNETCore;

using SignUp.Domain.Service;

using SignUp.Infrastructure;

using SignUp.WebApi.ViewModels;

using SignUp.WebApi.ViewModels.System;

namespace SignUp.WebApi.Controllers

{

    [Route("api/[controller]/[action]")]

    [ApiController]

    public class SystemController : ControllerBase

    {

        private readonly ISystemDomainService _systemDomainService;

        public SystemController(ISystemDomainService systemDomainService)

        {

            _systemDomainService = systemDomainService;

        }

        #region 用户管理

        [HttpPost]

        public async Task<ActionResult> GetUserList(PageGridRequest req)

        {

            return new JsonResult(await _systemDomainService.GetUserList(req.PageIndex, req.PageSize, req.Wheres, req.Sort, req.Order));

        }

        /// <summary>

        /// 添加菜单

        /// </summary>

        /// <remarks>

        /// 描述:添加菜单

        /// </remarks>

        /// <param name="req"></param>

        /// <returns></returns>

        [HttpPost]

        [UnitOfWork(typeof(SignUpDbContext))]

        public async Task<ActionResult> AddUser(AddUserRequest req)

        {

            return new JsonResult(await _systemDomainService.AddUser(req.UserName, req.Password, req.RealName, req.UserType));

        }

        /// <summary>

        /// 修改菜单

        /// </summary>

        /// <remarks>

        /// 描述:修改菜单

        /// </remarks>

        /// <param name="req"></param>

        /// <returns></returns>

        [HttpPut]

        [UnitOfWork(typeof(SignUpDbContext))]

        public async Task<ActionResult> EditUser(EditUserRequest req)

        {

            return new JsonResult(await _systemDomainService.EditUser(req.Id, req.UserName, req.RealName, req.UserType));

        }

        /// <summary>

        /// 删除人员

        /// </summary>

        /// <remarks>

        /// 描述:删除人员

        /// </remarks>

        /// <param name="id"></param>

        /// <returns></returns>

        [HttpDelete]

        [UnitOfWork(typeof(SignUpDbContext))]

        public async Task<ActionResult> DeleteUser(string id)

        {

            return new JsonResult(await _systemDomainService.DeleteUser(id));

        }

        /// <summary>

        /// 删除人员

        /// </summary>

        /// <remarks>

        /// 描述:删除人员

        /// </remarks>

        /// <param name="ids"></param>

        /// <returns></returns>

        [HttpDelete]

        [UnitOfWork(typeof(SignUpDbContext))]

        public ActionResult DeleteUserRange(string[] ids)

        {

            return new JsonResult(_systemDomainService.DeleteUserRange(ids));

        }

        #endregion

    }

}

删除仓储保存代码

1

2

3

4

5

6

public async Task<SysUser> AddUser(string userName, string password, string realName, string userType)

{

    SysUser model = SysUser.Add(userName, password, realName, userType);

    await _dbContext.SysUser.AddAsync(model);

    return model;

}

学习交流

附笔者学习 .net core开发时参考相关项目实例源码:asp.net core webapi项目实例源代码锦集下载(72个)

  • 19
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个简单的使用TransactionScope的代码示例,用于演示如何将多个数据库操作包装在一个事务中: ``` using System; using System.Data.SqlClient; using System.Transactions; class Program { static void Main() { // 创建一个连接字符串 string connectionString = "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=TestDB;Integrated Security=True"; // 创建一个事务范围对象 using (TransactionScope scope = new TransactionScope()) { try { // 执行第一个数据库操作 using (SqlConnection connection1 = new SqlConnection(connectionString)) { connection1.Open(); SqlCommand command1 = new SqlCommand("INSERT INTO Customers (Name) VALUES ('Customer 1')", connection1); command1.ExecuteNonQuery(); } // 执行第二个数据库操作 using (SqlConnection connection2 = new SqlConnection(connectionString)) { connection2.Open(); SqlCommand command2 = new SqlCommand("INSERT INTO Orders (CustomerId, OrderDate) VALUES ((SELECT TOP 1 Id FROM Customers ORDER BY Id DESC), GETDATE())", connection2); command2.ExecuteNonQuery(); } // 提交事务 scope.Complete(); } catch (Exception ex) { // 回滚事务 Console.WriteLine("Transaction rolled back: " + ex.Message); } } } } ``` 在这个示例中,我们使用TransactionScope类来创建一个事务范围,然后在这个范围内执行了两个数据库操作。如果两个操作都成功执行,我们调用了TransactionScope的Complete方法来提交事务。如果其中任何一个操作失败,我们就会在catch块中回滚事务

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值