同时支持EF+Dapper的混合仓储,助你快速搭建数据访问层
背景
17年開(kāi)始,公司開(kāi)始向DotNet Core轉(zhuǎn)型,面對(duì)ORM工具的選型,當(dāng)時(shí)圍繞Dapper和EF發(fā)生了激烈的討論。項(xiàng)目團(tuán)隊(duì)更加關(guān)注快速交付,他們主張使用EF這種能快速開(kāi)發(fā)的ORM工具;而在線業(yè)務(wù)團(tuán)隊(duì)對(duì)性能有更高的要求,他們更希望使用能直接執(zhí)行Sql語(yǔ)句的Dapper,這樣可控性更高。而對(duì)于架構(gòu)團(tuán)隊(duì)來(lái)說(shuō),滿足開(kāi)發(fā)團(tuán)隊(duì)的各種需求,提高他們的開(kāi)發(fā)效率是最核心的價(jià)值所在,所以當(dāng)時(shí)決定做一個(gè)混合型的既支持EF又支持dapper的數(shù)據(jù)倉(cāng)儲(chǔ)。
為什么選擇EF+Dapper
目前來(lái)說(shuō)EF和Dapper是.NET平臺(tái)最主流的ORM工具,團(tuán)隊(duì)成員的接受程度很高,相關(guān)的資料非常齊全,學(xué)習(xí)成本很低,各種坑也最少。
介紹
它不是一個(gè)ORM工具,它不做任何關(guān)于數(shù)據(jù)底層的操作
它是一個(gè)簡(jiǎn)易封裝的數(shù)據(jù)庫(kù)倉(cāng)儲(chǔ)和工作單元模型
能幫助你快速的構(gòu)建項(xiàng)目的數(shù)據(jù)訪問(wèn)層
經(jīng)過(guò)了2年多時(shí)間,10個(gè)項(xiàng)目組,大小近100多個(gè)線上項(xiàng)目的考驗(yàn)
支持EF和Dapper,可以在項(xiàng)目中隨意切換使用
支持工作單元模式,也支持傳統(tǒng)事務(wù)
支持Mysql和Mssql
支持同步和異步操作,推薦使用異步
PS: 簡(jiǎn)單操作使用EF,復(fù)雜sql操作使用Dapper是快速開(kāi)發(fā)的秘訣。
使用方法
引入nuget
<PackageReference Include="Leo.Chimp" Version="2.1.1" />創(chuàng)建實(shí)體對(duì)象,繼承IEntity
public class School : IEntity {public Guid Id { get; set; }public string Name { get; set; } }創(chuàng)建倉(cāng)儲(chǔ)接口和實(shí)現(xiàn)類,分別繼承IRepository和EfCoreRepository
public interface ISchoolRepository : IRepository<School> { } public class SchoolRepository: EfCoreRepository<School>,ISchoolRepository {public SchoolRepository(DbContext context) : base(context){} }創(chuàng)建上下文,繼承BaseDbContext,如果你不需要操作上下文可以不用做這一步
public class ChimpDbContext : BaseDbContext {public ChimpDbContext(DbContextOptions options) : base(options){}protected override void OnModelCreating(ModelBuilder modelBuilder){base.OnModelCreating(modelBuilder);//your code} }注入服務(wù)
services.AddChimp<ChimpDbContext>(opt =>opt.UseSqlServer("Server=10.0.0.99;Database=chimp;Uid=sa;Pwd=Fuluerp123") );如果你沒(méi)有創(chuàng)建上下文
services.AddChimp(opt =>opt.UseSqlServer("Server=10.0.0.99;Database=chimp;Uid=sa;Pwd=Fuluerp123") );在Controller中使用
public class ValuesController : ControllerBase {private readonly ISchoolRepository _schoolRepository;private readonly IUnitOfWork _unitOfWork;public ValuesController(ISchoolRepository schoolRepository, IUnitOfWork unitOfWork){_schoolRepository = schoolRepository;_unitOfWork = unitOfWork;} }詳細(xì)使用說(shuō)明
查詢
//根據(jù)主鍵查詢 _schoolRepository.GetById(Id)//不帶追蹤的查詢,返回?cái)?shù)據(jù)不能用于更新或刪除操作,性能快 schoolRepository.TableNoTracking.First(x => x.Id == Id);//帶追蹤的查詢,返回?cái)?shù)據(jù)可以用于更新或刪除操作,性能稍慢 schoolRepository.Table.First(x => x.Id == Id);//分頁(yè)查詢 _schoolRepository.TableNoTracking.ToPagedList(1,10);//sql語(yǔ)句查詢 _unitOfWork.QueryAsync<School>("select * from school"); //sql分頁(yè)查詢 _unitOfWork.QueryPagedListAsync<School>(1, 10, "select * from school order by id");關(guān)于查詢,暴露了返回IQueryable的TableNoTracking、Table這兩個(gè)屬性,讓開(kāi)發(fā)人員自己組裝Lambda表達(dá)式進(jìn)行查詢操作
新增
//新增,支持批量新增 _schoolRepository.Insert(school); await _unitOfWork.SaveChangesAsync();//sql語(yǔ)句新增 await _unitOfWork.ExecuteAsync("insert school(id,name) values(@Id,@Name)",school); await _unitOfWork.SaveChangesAsync();編輯
//編輯,支持批量編輯 var school = await _schoolRepository.GetByIdAsync(Id); school.Name="newschool"; _schoolRepository.Update(school); await _unitOfWork.SaveChangesAsync();//編輯,不用先查詢 var school = new School {Id = "xxxxxx",Name = "newschool" }; _schoolRepository.Update(school, x => x.Name); await _unitOfWork.SaveChangesAsync();//sql語(yǔ)句編輯 await _unitOfWork.ExecuteAsync("update school set name=@Name where id=@Id",school); await _unitOfWork.SaveChangesAsync();刪除
//刪除,支持批量刪除 _schoolRepository.Delete(school); await _unitOfWork.SaveChangesAsync();//根據(jù)lambda刪除 _schoolRepository.Delete(x => x.Id == Id); await _unitOfWork.SaveChangesAsync();事務(wù)
//工作單元模式使用事務(wù) await _schoolRepository.InsertAsync(school1); await _schoolRepository.InsertAsync(school2); await _unitOfWork.SaveChangesAsync();//dapper使用事務(wù) using (var tran = _unitOfWork.BeginTransaction()) {try{await _unitOfWork.ExecuteAsync("insert school(id,name) values(@Id,@Name)",school1,tran);await _unitOfWork.ExecuteAsync("insert school(id,name) values(@Id,@Name)",school2,tran);tran.Commit();}catch (Exception e){tran.Rollback();} }//dapper+ef混合使用事務(wù) using (var tran = _unitOfWork.BeginTransaction()) {try{await _schoolRepository.InsertAsync(school1);await _unitOfWork.SaveChangesAsync();await _unitOfWork.ExecuteAsync("insert school(id,name) values(@Id,@Name)",school2);tran.Commit();}catch (Exception e){tran.Rollback();} }高級(jí)用法
//通過(guò)GetConnection可以使用更多dapper擴(kuò)展的方法 await _unitOfWork.GetConnection().QueryAsync("select * from school");寫(xiě)在最后
Chimp核心是基于EF和Dapper的,所以EF和Dapper的功能都可以使用。比如導(dǎo)航屬性,字段映射等等。這個(gè)庫(kù)是線上項(xiàng)目核心依賴,會(huì)長(zhǎng)期更新維護(hù),希望大家能提出更好的意見(jiàn)。
項(xiàng)目地址v
數(shù)據(jù)庫(kù)腳本在根目錄的sqlscript文件夾里面 :https://github.com/longxianghui/chimp.git
原文鏈接:https://www.cnblogs.com/longxianghui/p/11635928.html
.NET社區(qū)新聞,深度好文,歡迎訪問(wèn)公眾號(hào)文章匯總?http://www.csharpkit.com?
總結(jié)
以上是生活随笔為你收集整理的同时支持EF+Dapper的混合仓储,助你快速搭建数据访问层的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 15年来这8门编程语言位置十分稳定,C#
- 下一篇: 向net core 3.0进击——Swa