本文实现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
)