倉儲(Repository)/工作單元(Unit Of Work)模式
- ?倉儲(rep):倉儲接口定義了對實體類訪問數(shù)據(jù)庫及操作的方法。它統(tǒng)一管理數(shù)據(jù)訪問的邏輯,并與業(yè)務邏輯層進行解耦。 簡單的理解就是對訪問數(shù)據(jù)庫的一層接口封裝。
- 工作單元(uow):用來保證我們處理業(yè)務邏輯的,穩(wěn)定性,完整性。防止在業(yè)務操作過程中,涉及對數(shù)據(jù)庫多張表進行了增刪改查(CURD)的時候,部分成功,部分失敗。類似數(shù)據(jù)庫中開的事務。
一.實現(xiàn)基礎的倉儲接口
1.新建一個 Repository (倉儲) 文件夾,用來存放我們定義各個實體類對數(shù)據(jù)庫操作的倉儲。也就是對各個實體(表)進行增刪改查的定義及實現(xiàn),以及更高級的操作,例,分頁,工作單元,事務,等等。
? ? ?1. 創(chuàng)建? 待辦事項倉儲接口類?IToDoRepository? 并且定義了(ToDo)實體對數(shù)據(jù)庫CURD 的方法?
public interface IToDoRepository
{
Task<bool> Add(ToDo toDo);
bool Delete(ToDo toDo);
bool Update(ToDo toDo);
Task<ToDo> GetToDo();
}
? ? ? 2. 創(chuàng)建待辦事項倉儲的?實現(xiàn)類?ToDoRepository。該類繼承自 IToDoRepository 倉儲接口類,并且需要實現(xiàn)父類所有定義的方法。
public class ToDoRepository : IToDoRepository
{
private readonly MyToDoContext doContext;
public ToDoRepository(MyToDoContext doContext)
{
this.doContext = doContext;
}
/// <summary>
/// 增加
/// </summary>
/// <param name="toDo"></param>
/// <returns></returns>
public async Task<bool> Add(ToDo toDo)
{
await doContext.ToDo.AddAsync(toDo);
return await doContext.SaveChangesAsync()>0;
}
/// <summary>
/// 刪除
/// </summary>
/// <param name="toDo"></param>
/// <returns></returns>
public bool Delete(ToDo toDo)
{
doContext.ToDo.Remove(toDo);
return doContext.SaveChanges()>0;
}
/// <summary>
/// 更新
/// </summary>
/// <param name="toDo"></param>
/// <returns></returns>
public bool Update(ToDo toDo)
{
doContext.ToDo.Update(new ToDo
{
Id = toDo.Id,
Title=toDo.Title,
Content=toDo.Content,
});
return doContext.SaveChanges()>0;
}
/// <summary>
/// 查詢
/// </summary>
/// <returns></returns>
public async Task<ToDo> GetToDo()
{
var toDo=await doContext.ToDo.FirstOrDefaultAsync();
return toDo;
}
}
- ?以上就是定義和實現(xiàn)的某個實體類倉儲的基礎寫法。并且接口命名規(guī)范要用大寫字母 I開頭,實現(xiàn)類就去掉 I 字母。例如:定義倉儲接口類: IToDoRepository, 倉儲接口實現(xiàn)類:ToDoRepository
- 執(zhí)行完操作后,要保存到數(shù)據(jù)庫,需要調用?SaveChangesAsync。異步方法需要加Async,同步方法則去掉Async.其他的方法使用異步或同步也是同樣的道理。
?二.如何使用倉儲
? ? 1. 在 Program.cs 中,進行注入
builder.Services.AddScoped<IToDoRepository,ToDoRepository>();
? ? ?2. 在控制器構造函數(shù)中實例化定義的倉儲接口,并且通過 toDoRepository 實例去調用到定義的方法。
namespace MyToDo.Api.Controllers
{
[ApiController]
[Route("[controller]/[action]")]
public class WeatherForecastController : ControllerBase
{
private readonly IToDoRepository toDoRepository;
public WeatherForecastController(IToDoRepository toDoRepository)
{
this.toDoRepository = toDoRepository;
}
[HttpGet(Name = "GetToDo")]
public async Task<ToDo> Get()
{
var retsult= await toDoRepository.GetToDo();
return retsult;
}
[HttpPost(Name = "Add")]
public async Task<bool> AddAsync(ToDo toDo)
{
var retsult = await toDoRepository.Add(toDo);
return retsult;
}
[HttpDelete(Name = "Delete")]
public bool Deletes(ToDo toDo)
{
var retsult = toDoRepository.Delete(toDo);
return retsult;
}
[HttpPost(Name = "Update")]
public bool UpdateAsync(ToDo toDo)
{
var retsult = toDoRepository.Update(toDo);
return retsult;
}
}
}
- 測試接口的時候,點擊Try in out,再執(zhí)行 Execute.如果沒有問題,就能看到查詢返回的數(shù)據(jù)了。
- 注意:控制器里面的添加的路由,已經(jīng)改成完整的路由了。由控制器/方法組合而成的唯一路由。例如:??[Route("[controller]/[action]")]
- 以上實現(xiàn)了 ToDo 實體對數(shù)據(jù)庫基礎的增刪改查,雖然實際應用中還遠遠達不到使用需求,這個只是為了能去理解倉儲模式的建立和使用。所有倉儲底層操作數(shù)據(jù)庫都大同小異。如果有別人寫好的倉儲,各性能各方面都相當ok,或者有其他的更主流的 orm框架,我們拿來用即可。避免重復造輪子,除非能造出更好的輪子了。
三.工作單元 (Unit Of Work)
- 自個實現(xiàn)的倉儲太簡單,在實際應用中,如果涉及多張表操作,暫時無法保證數(shù)據(jù)的一致性??赡苓€需要花很多時間去修改代碼達到使用需求。所以在 github 中已經(jīng)有更好的實現(xiàn)方案 UnitOfWork,也包含了倉儲接口的定義,直接拿來用即可。
- 使用 uow 好處,多個倉儲之間可以共享上下文(DbContext)以及保證操作數(shù)據(jù)一致性和完整性。
?1.? 下載 Unit Of Work 源碼
?2.在MyToDo.Api 項目中,創(chuàng)建一個?UnitOfWork 文件夾,并且把以下代碼復制過來
?3. 創(chuàng)建一個類庫項目去存放,共用的代碼
4.選擇 類庫項目,點下一步,并且項目名稱定義成 :MyToDo.Shared
5.把共用的代碼,復制到 MyToDo.Shared 里面去
6.在MyToDo.Api 項目中,右鍵=》添加=》項目引用
7.勾選 MyToDo.Shared。表示在 MyToDo.Api引用該項目,點擊確定。
8.最后,還需要在MyToDo.Api 項目的NuGet 中下載安裝這個包
Microsoft.EntityFrameworkCore.AutoHistory?
- 復制過來的代碼,命名空間要更改。如果有其他報錯,例如:報某個方法訪問性不一至,找到那個方法。把訪問修飾符?internal 改成public 就可以了。
?UnitOfWork 文件夾的源碼以及?MyToDo.Shared 等2個公共文件夾里面的源碼,自行去github下載了
- 目前,整個完整的項目結構,如下:
四.如何使用工作單元 (Unit Of Work)
1. 先添加不同倉儲的實現(xiàn),例如,待辦事項倉儲?(ToDoRepository)?
public class ToDoRepository : Repository<ToDo>, IRepository<ToDo>
{
public ToDoRepository(MyToDoContext dbContext) : base(dbContext)
{
}
}
這個就是使用別人提供的 Unit Of Work中已寫好的倉儲接口,然后自己自定義倉儲去繼承并實現(xiàn)它的一個標準寫法。這樣就能調用到別人集成好的方法。集成到自己的業(yè)務邏輯中去。
2.在Program.cs 中進行依賴注入
builder.Services.AddDbContext<MyToDoContext>(option =>
{
//獲取數(shù)據(jù)庫連接
var connectionString = builder.Configuration.GetConnectionString("ToDoConnection");
//使用sqlite
option.UseSqlite(connectionString);
}).AddUnitOfWork<MyToDoContext>() //注入工作單元
.AddCustomRepository<ToDo,ToDoRepository>() //注入倉儲
.AddCustomRepository<Memo, MemoRepository>()
.AddCustomRepository<User, UserRepository>();
文章來源:http://www.zghlxwxcb.cn/news/detail-784541.html
?3.使用方式
namespace MyToDo.Api.Controllers
{
[ApiController]
[Route("[controller]/[action]")]
public class WeatherForecastController : ControllerBase
{
private readonly IUnitOfWork unitOfWork;
public WeatherForecastController(IUnitOfWork unitOfWork)
{
this.unitOfWork = unitOfWork;
}
[HttpGet(Name = "GetToDo")]
public async Task<List<ToDo>> Get()
{
var service= unitOfWork.GetRepository<ToDo>();//獲取倉儲服務
return (List<ToDo>)await service.GetAllAsync();
}
}
}
4.最后效果
文章來源地址http://www.zghlxwxcb.cn/news/detail-784541.html
到了這里,關于Wpf 使用 Prism 實戰(zhàn)開發(fā)Day11的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!