Dapper UOW+事物AOP

本文介绍如何在.NET Core项目中利用Dapper和AOP(以PostSharp为例)来实现数据库操作的事务处理。首先创建Core项目,然后定义DbSession、IUnitOfWork和UnitOfWork接口及其实现。接着,创建NotificationRepository数据操作类,并在Startup中注册相关依赖。通过TransactionsAttribute实现AOP事务处理,最后在HomeController中展示如何在控制器中使用事务。

本文实现Dapper操作数据统一提交和事物的AOP操作

1、新建个core项目

2、添加DbSession类

using System;
using System.Data;
using System.Data.Common;

namespace DapperUowTests.Data
{
    public sealed class DbSession : IDisposable
    {
        public IDbConnection Connection { get; }
        public IDbTransaction Transaction { get; set; }

        public DbSession(DbConnection connection)
        {
            Connection = connection;
            Connection.Open();
        }

        public void Dispose() => Connection?.Dispose();
    }
}

2、添加IUnitOfWork接口

using System;

namespace DapperUowTests.Data
{
    public interface IUnitOfWork : IDisposable
    {
        void BeginTransaction();
        void Commit();
        void Rollback();
    }
}

3、实现接口UnitOfWork

using System.ComponentModel.Composition;
using System.Data;

namespace DapperUowTests.Data
{
    public sealed class UnitOfWork : IUnitOfWork
    {
        private readonly DbSession _session;

        public UnitOfWork(DbSession session)
        {
            _session = session;
        }

        public void BeginTransaction()
        {
            _session.Transaction = _session.Connection.BeginTransaction();
        }

        public void Commit()
        {
            _session.Transaction.Commit();
            Dispose();
        }

        public void Rollback()
        {
            _session.Transaction.Rollback();
            Dispose();
        }

        public void Dispose() => _session.Transaction?.Dispose();
    }
}

4、添加数据操作类NotificationRepository

using System;
using System.Collections.Generic;
using Dapper;

namespace DapperUowTests.Data
{
    public class NotificationRepository
    {
        private DbSession _session;

        public NotificationRepository(DbSession session)
        {
            _session = session;
        }

        public IEnumerable<NotificationModel> Get()
        {
            return _session.Connection.Query<NotificationModel>("SELECT * FROM [Notifications]", null, _session.Transaction);
        }

        public void Save(NotificationModel model)
        {
            _session.Connection.Execute("INSERT INTO [Notifications] VALUES(NEWID(), 'Title', 'URL', GETDATE())", null, _session.Transaction);
        }
    }

    public class NotificationModel
    {
        public Guid Id { get; set; }
        public string Title { get; set; }
        public string Url { get; set; }
        public DateTime Date { get; set; }
    }
}

5、Startup添加以上注入

services.AddScoped<DbConnection>(provider =>
            {
                return new System.Data.SqlClient.SqlConnection("Data Source=.;Initial Catalog=dbTest;UID=sa;PWD=123456;MultipleActiveResultSets=True");
            });           
services.AddScoped<DbSession>();
services.AddTransient<IUnitOfWork, UnitOfWork>();
services.AddTransient<NotificationRepository>();

6、添加事物AOP TransactionsAttribute,这里是用的PostSharp做的一个AOP实现,他的底层是IL写的,这是他的官方文档PostSharp Documentation - PostSharp 6.10 Documentation

/// <summary>
    /// 事物AOP
    /// </summary>
    [PSerializable]
    [ProvideAspectRole(StandardRoles.TransactionHandling)]
    [AspectRoleDependency(AspectDependencyAction.Order, AspectDependencyPosition.After, StandardRoles.Caching)]
    public class TransactionsAttribute : MethodInterceptionAspect
    {
        public override void OnInvoke(MethodInterceptionArgs args)
        {
            if (args.Instance is ControllerBase cb)
            {
                var unitOfWorkService = cb.HttpContext.RequestServices.GetService(typeof(IUnitOfWork)) as IUnitOfWork;//必须要用当前的作用域进行手动的获取注入接口,因为我上面的DbSession是Scoped的注入方式

                unitOfWorkService.BeginTransaction();

                base.OnInvoke(args);

                unitOfWorkService.Commit();
            }
        }
    }

6、添加HomeController

    [ApiController]
    [Route("")]
    public class HomeController : ControllerBase
    {
        [HttpGet("")]
        public IEnumerable<NotificationModel> Get(
            [FromServices] NotificationRepository repository)
        {
            return repository.Get();
        }

        [HttpPost("")]
        [Transactions]//这里保存运用事物操作
        public IActionResult Post(
            [FromServices] NotificationRepository repository)
        {
            repository.Save(new NotificationModel
            {
                Date = DateTime.Now,
                Id = Guid.NewGuid(),
                Title = "Teste",
                Url = "Teste"
            });
           
            return Ok();
        }
    }

数据库表结构

CREATE TABLE [dbo].[Notifications] (
  [Id] uniqueidentifier  NOT NULL,
  [Title] varchar(255) COLLATE Chinese_PRC_CI_AS  NULL,
  [Url] varchar(255) COLLATE Chinese_PRC_CI_AS  NULL,
  [Date] datetime  NULL
)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值