• Dapper是什么?


    Dapper是开源的、轻量级,高性能的ORM(对象关系映射)。

    Dapper的特点:

    一、轻量:Dapper的GitHub地址:https://github.com/StackExchange/Dapper/tree/main/Dapper,它的核心代码是SqlMapper.cs。代码量不多,编辑后所占空间也比较小。

    二、高性能:它通过Emit反射IDataReader的序列队列,快速的映射出对象。

    三、Dapper更倾向于面向SQL,支持多种数据库。

     .NetCore中简单封装使用Dapper

    1、引入Dapper和Dapper.Contrib

    2、创建仓储接口

    复制代码
     1 public interface IRepository<T> where T:BaseEntity
     2     {
     3         T GetById(string id);
     4         IEnumerable<T> GetAll();
     5         IEnumerable<T> GetBySql(string sql, Dictionary<string, object> parameter, CommandType commandType);
     6         IEnumerable<T> GetByPaging(string sql, Dictionary<string, object> parameters, CommandType commandType);
     7        
     8         void Add(T entity);
     9         void Delete(T entity);
    10         void Update(T Entity);
    11 
    12     }
    复制代码

    3、创建仓储基类

    复制代码
     1    public class BaseRepository<T> : IRepository<T> where T : BaseEntity
     2     {
     3         private IDbConnection _connection;
     4         public BaseRepository(IConfiguration configuration)
     5         {
     6             this._connection = new MySqlConnection(configuration.GetConnectionString("ListingDb"));
     7         }
     8 
     9         public IEnumerable<T> GetAll()
    10         {
    11             var result = _connection.GetAll<T>();
    12             return result;
    13         }
    14 
    15         public T GetById(string id)
    16         {
    17             var result = _connection.Get<T>(id);
    18             return result;
    19         }
    20 
    21         public IEnumerable<T> GetByPaging(string sql, Dictionary<string, object> parameters, CommandType commandType)
    22         {
    23             //TODO query paging
    24             return null;
    25         }
    26 
    27         public IEnumerable<T> GetBySql(string sql, Dictionary<string, object> parameters, CommandType commandType)
    28         {
    29             var result = _connection.Query<T>(sql, parameters, commandType: commandType);
    30             return result;
    31         }
    32 
    33         public void Add(T entity)
    34         {
    35             _connection.Insert(entity, null);
    36         }
    37         public void Update(T entity)
    38         {
    39             _connection.Update(entity);
    40         }
    41         public void Delete(T entity)
    42         {
    43             _connection.Delete(entity);
    44         }
    45     }
    复制代码

    4、在startup.cs中注入仓储类

    services.AddScoped(typeof(IRepository<>), typeof(BaseRepository<>));

    5、定义具体业务类进行调用(略)

    进阶--实现Dapper+UnitOfWork

    想了解UOW(UnitOfWork)可参照:https://martinfowler.com/eaaCatalog/unitOfWork.html

    在【简单封装dapper】中,不难发现它主要是针对单个对象的操作。即使通过注入多个对象的仓储进行统一处理统一事务的多表,但是还是缺少了事务的支持。就像之前写的关于数据库访问的封装(https://www.cnblogs.com/johnyong/p/14152891.html)一样,需要将事务进行抽离,即做成单独的工作单元,实现对对象状态的跟踪,实现事务。

    以下是简单的实现

    1、定义IUnitOfWork接口

    复制代码
    1     public interface IUnitOfWork
    2     {
    3         Guid Id { get; }
    4         IDbConnection Connection { get; }
    5         IDbTransaction Transaction { get; }
    6         void Begin();
    7         void Commit();
    8         void Rollback(); 
    9     }
    复制代码

    2、定义UnitOfWork

    复制代码
     1     public sealed class UnitOfWork : IUnitOfWork, IDisposable
     2     {
     3         private Guid _id = Guid.Empty;
     4         private IDbConnection _connection = null;
     5         private IDbTransaction _transaction = null;
     6         private bool _disposed = false;
     7  
     8         public UnitOfWork(IConfiguration configuration)
     9         {
    10             _id = new Guid();
    11             _connection = new MySqlConnection(configuration.GetConnectionString("SimpleTestConnection"));
    12 
    13 
    14         }
    15 
    16 
    17         public Guid Id
    18         {
    19             get { return _id; }
    20         }
    21 
    22         public IDbConnection Connection
    23         {
    24             get { return _connection; }
    25         }
    26         public IDbTransaction Transaction
    27         {
    28             get { return _transaction; }
    29         }
    30 
    31         public void Begin()
    32         {
    33             if (_connection.State != ConnectionState.Open)
    34             {
    35                 _connection.Open();
    36             }
    37             _transaction = _connection.BeginTransaction();
    38         }
    39 
    40         public void Commit()
    41         {
    42             _transaction.Commit();
    43             Dispose();
    44         }
    45 
    46         public void Rollback()
    47         {
    48             _transaction.Rollback();
    49             Dispose();
    50         }
    51 
    52 
    53         public void Dispose()
    54         {
    55             Dispose(true);
    56             GC.SuppressFinalize(this);
    57         }
    58 
    59         public void Dispose(bool disposing)
    60         {
    61             if (_disposed)
    62                 return;
    63 
    64             if (disposing)
    65             {
    66                 _transaction?.Dispose();
    67                 _connection?.Dispose();
    68             }
    69 
    70             _transaction = null;
    71             _connection = null;
    72             _disposed = true;
    73         }
    74         ~UnitOfWork()
    75         {
    76             Dispose(false);
    77         }
    78     }
    复制代码

    3、修改BaseRepository

    复制代码
     1     public class BaseRepository<T> : IRepository<T> where T : BaseEntity
     2     {
     3         private IUnitOfWork _unitOfWork;
     4         public BaseRepository(IUnitOfWork unitOfWork)
     5         {
     6             this._unitOfWork = unitOfWork;
     7         }
     8        
     9         public IEnumerable<T> GetAll()
    10         {
    11             var result = _unitOfWork.Connection.GetAll<T>();
    12             return result;
    13         }
    14 
    15         public T GetById(string id)
    16         {
    17             var result = _unitOfWork.Connection.Get<T>(id);
    18             return result;
    19         }
    20 
    21         public IEnumerable<T> GetByPaging(string sql, Dictionary<string, object> parameters, CommandType commandType)
    22         {
    23             //TODO query paging
    24             return null; 
    25         }
    26 
    27         public IEnumerable<T> GetBySql(string sql, Dictionary<string, object> parameters, CommandType commandType)
    28         {
    29             var result = _unitOfWork.Connection.Query<T>(sql, parameters, commandType: commandType);
    30             return result;
    31         }
    32 
    33         public void Add(T entity)
    34         {
    35             _unitOfWork.Connection.Insert(entity,null);
    36         }
    37         public void Update(T entity)
    38         {
    39             _unitOfWork.Connection.Update(entity);
    40         }
    41         public void Delete(T entity)
    42         {
    43             _unitOfWork.Connection.Delete(entity);
    44         }
    45     }
    复制代码

    4、定义事务特性,用于实现aop(需要引入AspectCore.DynamicProxy)

    复制代码
     1     public class SystemTransactionAttribute : AbstractInterceptorAttribute
     2     {
     3         IUnitOfWork _unitOfWork { get; set; }
     4 
     5         public async override Task Invoke(AspectContext context, AspectDelegate next)
     6         {
     7             try
     8             {
     9                 _unitOfWork = context.ServiceProvider.GetService(typeof(IUnitOfWork)) as IUnitOfWork;
    10                 _unitOfWork.Begin();
    11                 await next(context);
    12                 _unitOfWork.Commit();
    13             }
    14             catch (Exception ex )
    15             {
    16                 _unitOfWork.Rollback();
    17                 throw new Exception("SystemTransaction error",ex);
    18             }
    19         }
    20     }
    复制代码

    5、注入服务

    在startup.cs注入UnitOfWork

                services.AddScoped<IUnitOfWork, UnitOfWork>();
                services.AddScoped(typeof(IRepository<>), typeof(BaseRepository<>));

    修改Program.cs

    复制代码
     1     public class Program
     2     {
     3         public static void Main(string[] args)
     4         {
     5             CreateHostBuilder(args).Build().Run();
     6         }
     7 
     8         public static IHostBuilder CreateHostBuilder(string[] args) =>
     9             Host.CreateDefaultBuilder(args)
    10                 .ConfigureWebHostDefaults(webBuilder =>
    11                 {
    12                     webBuilder.UseStartup<Startup>();
    13                 }).UseDynamicProxy();
    14     }
    复制代码

    6、测试示例代码

    复制代码
     1     public class ListingService: IListingService
     2     {
     3         private IRepository<Listing> _listingRepository;
     4         private IRepository<ListingDetail> _listingDetailRepository;
     5 
     6         public ListingService(IRepository<Listing> listingRepository,IRepository<ListingDetail> listingDetailRepository)
     7         {
     8             this._listingRepository = listingRepository;
     9             this._listingDetailRepository = listingDetailRepository;
    10         }
    11         [SystemTransaction]
    12         public void AddListing(ListingContract contract)
    13         { 
    14             var listing = new Listing()
    15             {
    16                 Id = ObjectId.GenerateNewId().ToString(), 
    17                 Price = contract.Price,
    18                 Quantity = contract.Quantity,
    19                 Title=contract.Title,
    20                 Remark="john_yong test"
    21             };
    22             _listingRepository.Add(listing);
    23             foreach (var item in contract.DetailList)
    24             {
    25                 var listingDetail = new ListingDetail()
    26                 {
    27                     Id ="",//设置Id为空抛出异常 //ObjectId.GenerateNewId().ToString(),
    28                     ListingId = listing.Id,
    29                     Quantity = item.Quantity,
    30                     SKU = item.SKU,
    31                 };
    32                 _listingDetailRepository.Add(listingDetail);
    33             } 
    34             
    35         }
    36     }
    复制代码

    注:

    使用dapper.Contrib,默认数据库表明为实体名称的复数形式,我们可以使用[Table]特性进行声明表名称。

    Dapper.Contrib.Extensions扩展而言:自增主键用[Key]标志(默认为自增主键),非自增主键必须用[ExplicitKey]标志,否则即使我们给Id指定值再进行插入数据表,最终Id还是为空。

    --------------------

    本文地址: https://www.cnblogs.com/johnyong/p/14433155.html

    转 https://www.cnblogs.com/johnyong/p/14433155.html

  • 相关阅读:
    实验一 命令解释程序
    复利计算器3.0更新版
    复利计算器3.0总结
    复利计算器2.0
    0414复利计算5.1-美观、输入更新
    0408结对汉堡-结对2.0
    0406复利计算程序5.0-结对编程
    《构建之法》第四章读后感
    复利计算4.0-单元测试
    操作系统实验一、 命令解释程序的编写
  • 原文地址:https://www.cnblogs.com/wl-blog/p/15220966.html
Copyright © 2020-2023  润新知