同時支援EF+Dapper的混合倉儲,助你快速搭建資料訪問層
阿新 • • 發佈:2019-10-08
背景
17年開始,公司開始向DotNet Core轉型,面對ORM工具的選型,當時圍繞Dapper和EF發生了激烈的討論。專案團隊更加關注快速交付,他們主張使用EF這種能快速開發的ORM工具;而線上業務團隊對效能有更高的要求,他們更希望使用能直接執行Sql語句的Dapper,這樣可控性更高。而對於架構團隊來說,滿足開發團隊的各種需求,提高他們的開發效率是最核心的價值所在,所以當時決定做一個混合型的既支援EF又支援dapper的資料倉儲。
為什麼選擇EF+Dapper
目前來說EF和Dapper是.NET平臺最主流的ORM工具,團隊成員的接受程度很高,相關的資料非常齊全,學習成本很低,各種坑也最少。
介紹
- 它不是一個ORM工具,它不做任何關於資料底層的操作
- 它是一個簡易封裝的資料庫倉儲和工作單元模型
- 能幫助你快速的構建專案的資料訪問層
- 經過了2年多時間,10個專案組,大小近100多個線上專案的考驗
- 支援EF和Dapper,可以在專案中隨意切換使用
- 支援工作單元模式,也支援傳統事務
- 支援Mysql和Mssql
- 支援同步和非同步操作,推薦使用非同步
PS: 簡單操作使用EF,複雜sql操作使用Dapper是快速開發的祕訣。
使用方法
引入nuget
<PackageReference Include="Leo.Chimp" Version="2.1.1" />
建立實體物件,繼承IEntity
public class School : IEntity
{
public Guid Id { get; set; }
public string Name { get; set; }
}
建立倉儲介面和實現類,分別繼承IRepository和EfCoreRepository
public interface ISchoolRepository : IRepository<School> { } public class SchoolRepository: EfCoreRepository<School>,ISchoolRepository { public SchoolRepository(DbContext context) : base(context) { } }
建立上下文,繼承BaseDbContext,如果你不需要操作上下文可以不用做這一步
public class ChimpDbContext : BaseDbContext
{
public ChimpDbContext(DbContextOptions options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
//your code
}
}
注入服務
services.AddChimp<ChimpDbContext>(
opt =>
opt.UseSqlServer("Server=10.0.0.99;Database=chimp;Uid=sa;Pwd=Fuluerp123")
);
如果你沒有建立上下文
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;
}
}
詳細使用說明
查詢
//根據主鍵查詢
_schoolRepository.GetById(Id)
//不帶追蹤的查詢,返回資料不能用於更新或刪除操作,效能快
schoolRepository.TableNoTracking.First(x => x.Id == Id);
//帶追蹤的查詢,返回資料可以用於更新或刪除操作,效能稍慢
schoolRepository.Table.First(x => x.Id == Id);
//分頁查詢
_schoolRepository.TableNoTracking.ToPagedList(1,10);
//sql語句查詢
_unitOfWork.QueryAsync<School>("select * from school");
//sql分頁查詢
_unitOfWork.QueryPagedListAsync<School>(1, 10, "select * from school order by id");
關於查詢,暴露了返回IQueryable的TableNoTracking、Table這兩個屬性,讓開發人員自己組裝Lambda表示式進行查詢操作
新增
//新增,支援批量新增
_schoolRepository.Insert(school);
await _unitOfWork.SaveChangesAsync();
//sql語句新增
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語句編輯
await _unitOfWork.ExecuteAsync("update school set name=@Name where id=@Id",school);
await _unitOfWork.SaveChangesAsync();
刪除
//刪除,支援批量刪除
_schoolRepository.Delete(school);
await _unitOfWork.SaveChangesAsync();
//根據lambda刪除
_schoolRepository.Delete(x => x.Id == Id);
await _unitOfWork.SaveChangesAsync();
事務
//工作單元模式使用事務
await _schoolRepository.InsertAsync(school1);
await _schoolRepository.InsertAsync(school2);
await _unitOfWork.SaveChangesAsync();
//dapper使用事務
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混合使用事務
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();
}
}
高階用法
//通過GetConnection可以使用更多dapper擴充套件的方法
await _unitOfWork.GetConnection().QueryAsync("select * from school");
寫在最後
Chimp核心是基於EF和Dapper的,所以EF和Dapper的功能都可以使用。比如導航屬性,欄位對映等等。這個庫是線上專案核心依賴,會長期更新維護,希望大家能提出更好的意見。
QQ群:687800650 有問題可以加群交流
專案地址
資料庫指令碼在根目錄的sqlscript資料夾裡面
github地址