GitHub:https://github.com/iamoldli/NetModularhtml
地址:https://nm.iamoldli.com
帳戶:admin
密碼:admin前端
地址:http://nm.demo.iamoldli.com/index.html
帳戶:admin
密碼:admingit
一、開篇
二、快速建立一個業務模塊
三、數據訪問模塊介紹
四、模塊化實現思路github
NetModular
的數據訪問模塊是基於 Dapper 擴展的輕量級的ORM,它自己是徹底獨立的,能夠在任何項目中直接使用。在NetModular
中也提供了擴展,可以完美的與模塊化集成在一塊兒。數據庫
NetModular
自己已經作好了集成,因此業務模塊中,能夠直接寫代碼,不用考慮注入的問題,若是想要了解它的集成邏輯的,能夠查看Data.AspNetCore
庫前端框架
Node: 數據庫上下文、倉儲和工做單元的注入方式採用的是
Scoped
app
數據庫上下文須要繼承DbContext
框架
public class MallDbContext : DbContext { public MallDbContext(IDbContextOptions options) : base(options) { } }
實體須要繼承IEntity
接口,在NetModular
中,已經提供了幾個通用的實體基類,而且內部已經實現了對應的功能,好比EntityBase
:異步
public class EntityBase<TKey> : Entity<TKey> { /// <summary> /// 建立時間 /// </summary> public DateTime CreatedTime { get; set; } = DateTime.Now; /// <summary> /// 建立人 /// </summary> public Guid CreatedBy { get; set; } /// <summary> /// 修改時間 /// </summary> public DateTime ModifiedTime { get; set; } = DateTime.Now; /// <summary> /// 修改人 /// </summary> public Guid ModifiedBy { get; set; } /// <summary> /// 建立人名稱 /// </summary> [Ignore] public string Creator { get; set; } /// <summary> /// 修改人 /// </summary> [Ignore] public string Modifier { get; set; } }
能夠看到 EntityBase
已經包含了CreatedTime
,CreatedBy
,ModifiedTime
,ModifiedBy
這四個實體屬性,經過實體繼承了EntityBase
,那麼該實體也包含了這個屬性,同時NetModular
內部已經實現了在添加,修改時,自動設置對應的建立人和修改人編號,因此你不須要你去考慮這些事情了。async
另外還有包含軟刪除功能的EntityWithSoftDelete
以及包含上面兩個實體功能的EntityBaseWithSoftDelete
兩個實體,這些都已經封裝好了,能夠直接用。
Node: 上面的三個實體基類都會繼承自
Entity
,該實體包含了一個主鍵Id
,主鍵類型支持Guid(默認)、Int、Long三種類型。
能夠經過Table特性,設置實體對應的表名稱
如下是一個產品的實體示例:
[Table("Product")] public partial class ProductEntity : EntityBase { /// <summary> /// 標題 /// </summary> public string Title { get; set; } /// <summary> /// 價格 /// </summary> public decimal Price { get; set; } /// <summary> /// 庫存 /// </summary> public int Store { get; set; } /// <summary> /// 狀態 /// </summary> public ProductStatus Status { get; set; } }
實體擴展類:
Node: 實體擴展類中的屬性,必須添加Ignore
特性,不然屬性會被當成表的列處理。
public partial class ProductEntity { /// <summary> /// sku列表 /// </summary> [Ignore] public List<Guid> Skus { get; set; } }
倉儲接口必須繼承IRepository<>
接口
/// <summary> /// 產品倉儲接口 /// </summary> public interface IProductRepository : IRepository<ProductEntity> { /// <summary> /// 查詢 /// </summary> /// <param name="model"></param> /// <returns></returns> Task<IList<ProductEntity>> Query(ProductQueryModel model); }
查詢模型包含查詢條件,須要繼承QueryModel
類,該類包含了分頁相關的信息
public class ProductQueryModel : QueryModel { public string Title { get; set; } }
倉儲實現須要繼承抽象倉儲RepositoryAbstract<>
,不一樣數據庫的倉儲實現,須要放到不一樣的目錄中。由於不一樣的數據庫不免會有一些查詢,因此咱們採用先實現一種數據庫的實現,而後其它數據實現直接繼承它,對於有查詢的方法,採用覆寫的方式實現。
public class ProductRepository : RepositoryAbstract<ProductEntity>, IProductRepository { public ProductRepository(IDbContext context) : base(context) { } public async Task<IList<ProductEntity>> Query(ProductQueryModel model) { //分頁 var paging = model.Paging(); var query = Db.Find(); query.WhereIf(model.Title.NotNull(), m => m.Title.Contains(model.Title)); //設置默認排序 if (!paging.OrderBy.Any()) { query.OrderByDescending(m => m.Id); } var list = await query.PaginationAsync(paging); model.TotalCount = paging.TotalCount; return list; } }
上面的例子是一個最簡單的分頁查詢,到此數據訪問的代碼就寫完了,剩下的就是在服務層調用就好了。
基礎的CRUD在RepositoryAbstract
中已經實現了,因此能夠直接在服務中調用
新增
_repository.AddAsync(entity);
批量新增
_repository.AddAsync(entities);
刪除
_repository.DeleteAsync(id);
軟刪除
_repository.SoftDeleteAsync(id);
修改
_repository.UpdateAsync(entity);
獲取
_repository.GetAsync(id);
獲取全部
_repository.GetAllAsync()
是否存在
_repository.ExistsAsync(m => m.Title.Contains("test"))
/// <summary> /// 批量修改狀態 /// </summary> /// <param name="ids"></param> /// <param name="status"></param> /// <returns></returns> public Task<bool> UpdateStatus(List<Guid> ids, ProductStatus status) { return Db.Find(m => ids.Contains(m.Id)).UpdateAsync(m => new ProductEntity { Status = status }); }
/// <summary> /// 批量刪除 /// </summary> /// <param name="title"></param> /// <returns></returns> public Task<bool> Delete(string title) { return Db.Find(m => m.Title.Contains(title)).DeleteAsync(); }
public async Task<IList<ProductEntity>> Query(ProductQueryModel model) { //分頁 var paging = model.Paging(); var query = Db.Find(); query.WhereIf(model.Title.NotNull(), m => m.Title.Contains(model.Title)); //設置默認排序 if (!paging.OrderBy.Any()) { query.OrderByDescending(m => m.Id); } var list = await query.LeftJoin<AccountEntity>((x, y) => x.CreatedBy == y.Id) .Select((x, y) => new { x, Creator = y.Name }) .PaginationAsync(paging); model.TotalCount = paging.TotalCount; return list; }
Db.Find().GroupBy(m => new { m.Status }).Select(m => new { m.Key.Status, Count = m.Count() });
工做單元在服務中注入使用
private readonly IUnitOfWork _uow; public ArticleService(IUnitOfWork<MalDbContext> uow) { _uow = uow; }
而後經過BeginTransaction
方法開啓事務,Commit
方法提交事務,Rollback
方法回滾事務
_uow.BeginTransaction(); var result = await _accountRepository.AddAsync(account); if (result) { if (model.Roles != null && model.Roles.Any()) { var accountRoleList = model.Roles.Select(m => new AccountRoleEntity { AccountId = account.Id, RoleId = m }).ToList(); if (await _accountRoleRepository.AddAsync(accountRoleList)) { _uow.Commit(); return ResultModel.Success(); } } else { _uow.Commit(); return ResultModel.Success(); } }
好了,數據庫訪問的用法大體就是這樣~