源码

GitHub:https://github.com/iamoldli/NetModular

演示地址

地址:https://nm.iamoldli.com

账户:admin

密码:admin

前端框架演示地址(临时)

地址:http://nm.demo.iamoldli.com/index.html

账户:admin

密码:admin

目录

1、开篇

2、快速创建一个业务模块

3、数据访问模块介绍

4、模块化实现思路

简介

NetModular 的数据访问模块是基于 Dapper 扩展的轻量级的ORM,它本身是完全独立的,可以在任何项目中直接使用。在NetModular中也提供了扩展,能够完美的与模块化集成在一起。

支持的功能

  • [x] 支持SqlServer、MySql、SQLite数据库
  • [x] 基础的CRUD方法
  • [x] 批量添加、删除、修改
  • [x] 修改指定列
  • [x] Lamdba表达式支持
  • [x] 多表连接查询
  • [x] 分页查询
  • [x] 分组查询
  • [x] 仓储模式
  • [x] 工作单元
  • [x] 自定义表名、列名
  • [x] 支持同步/异步方法

使用方法

NetModular 本身已经做好了集成,所以业务模块中,可以直接写代码,不用考虑注入的问题,如果想要了解它的集成逻辑的,可以查看Data.AspNetCore

Node: 数据库上下文、仓储和工作单元的注入方式采用的是Scoped

1、添加数据库上下文

数据库上下文需要继承DbContext

    public class MallDbContext : DbContext
{
public MallDbContext(IDbContextOptions options) : base(options)
{
}
}

2、创建实体

实体需要继承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内部已经实现了在添加,修改时,自动设置对应的创建人和修改人编号,所以你不需要你去考虑这些事情了。

另外还有包含软删除功能的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; }
}

3、添加仓储接口

仓储接口必须继承IRepository<>接口

/// <summary>
/// 产品仓储接口
/// </summary>
public interface IProductRepository : IRepository<ProductEntity>
{
/// <summary>
/// 查询
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
Task<IList<ProductEntity>> Query(ProductQueryModel model);
}

4、添加查询模型

查询模型包含查询条件,需要继承QueryModel类,该类包含了分页相关的信息

public class ProductQueryModel : QueryModel
{
public string Title { get; set; }
}

5、添加仓储实现

仓储实现需要继承抽象仓储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;
}
}

上面的例子是一个最简单的分页查询,到此数据访问的代码就写完了,剩下的就是在服务层调用就行了。

其它用法说明

1、CRUD

基础的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();
}
}

好了,数据库访问的用法大致就是这样~

ASP.NET Core模块化前后端分离快速开发框架介绍之3、数据访问模块介绍的更多相关文章

  1. ASP.NET Core模块化前后端分离快速开发框架介绍之4、模块化实现思路

    源码 GitHub:https://github.com/iamoldli/NetModular 演示地址 地址:https://nm.iamoldli.com 账户:admin 密码:admin 前 ...

  2. ASP.NET Core模块化前后端分离快速开发框架介绍之2、快速创建一个业务模块

    源码地址 GitHub:https://github.com/iamoldli/NetModular 演示地址 地址:https://nm.iamoldli.com 账户:admin 密码:admin ...

  3. ASP.NET Core模块化前后端分离快速开发框架介绍之1、开篇

    源码地址 GitHub:https://github.com/iamoldli/NetModular 演示地址 地址:https://nm.iamoldli.com 账户:admin 密码:admin ...

  4. .Net Core+Vue.js模块化前后端分离快速开发框架NetModular更新日志(2019-12-08)

    源码 GitHub:https://github.com/iamoldli/NetModular 码云:https://gitee.com/laoli/NetModular 欢迎star~ 文档 ht ...

  5. .NET Core前后端分离快速开发框架(Core.3.0+AntdVue)

    .NET Core前后端分离快速开发框架(Core.3.0+AntdVue) 目录 引言 简介 环境搭建 开发环境要求 基础数据库构建 数据库设计规范 运行 使用教程 全局配置 快速开发 管理员登录 ...

  6. [转].NET Core前后端分离快速开发框架(Core.3.0+AntdVue)

    [转].NET Core前后端分离快速开发框架(Core.3.0+AntdVue) 目录 引言 简介 环境搭建 开发环境要求 基础数据库构建 数据库设计规范 运行 使用教程 全局配置 快速开发 管理员 ...

  7. .Net Core与Vue.js模块化前后端分离快速开发解决方案(NetModular)

    NetModular是什么? NetModular不仅仅是一个框架,它也是一整套的模块化与前后端分离的快速开发的解决方案,目标是致力于开箱即用,让开发人员完全专注于业务开发,不需要关心底层封装和实现. ...

  8. 前后端分离后API交互如何保证数据安全性

    前后端分离后API交互如何保证数据安全性? 一.前言 前后端分离的开发方式,我们以接口为标准来进行推动,定义好接口,各自开发自己的功能,最后进行联调整合.无论是开发原生的APP还是webapp还是PC ...

  9. 优秀开源平台,前后端分离快速开发平台,一站式多端开发(PC+APP)

    JNPF平台架构介绍 JNPF快速开发平台采用前后端分离技术.采用B/S架构开发,形成一站式开发多端(APP+PC)使用. PC端版本介绍 第一个当然是当下热门的.net core了,运行环境为Vis ...

随机推荐

  1. ZK数据同步

    整个集群完成Learner选举后,Learner向Leader发起注册,然后进入数据同步环节,即Leader将learner上缺失的事务请求同步给Learner 1). 获取Learner状态 根据L ...

  2. <Linux系统isosize指令用法>

    isosize命令:iso9660文件系统大小显示 isosize命令用于显示iso9660文件系统的大小,还文件可以使普通文件,也可以是块设备,如/dev/sr0或者/dev/sda.如果没有相关选 ...

  3. linux 解决 gvfsd-smb-browse CPU 100%占用

    原文地址:https://bugzilla.redhat.com/show_bug.cgi?id=1303300 1: sudo vim /etc/samba/smb.conf 2:定位到[globa ...

  4. Java并发基础:线程的创建

    线程的创建和管理: 1.应用Thread类显式创建.管理线程 2.应用Executor创建并管理线程. 定义任务: 无返回的任务:实现Runnable接口并编写run()方法. 有响应的任务:实现Ca ...

  5. 子元素的margin-top会影响父元素

    ---恢复内容开始--- 之前在写项目的时候,发现原本想让父子元素之间加点边距,却让父元素产生了margin-top,于是百度之后发现了原因. 在css2.1盒模型中 In this specific ...

  6. 服网LNMP集群-1.0.5

    平台: arm 类型: ARM 模板 软件包: haproxy linux mysql nginx application server arm basic software fuwang infra ...

  7. 域名与IP地址的联系与区别

    我们也知道每一台机都有一个唯一ip地址, 特别难记,所以出现了今天的DNS(域名) 当我们的计算机想要和一个远程机器连接时,我们可以申请连接该机器ip地址下的DNS,例如:www.baidu.com. ...

  8. v-if与v-show的区别

    一.区别 v-if 动态的向DOM树内添加或者删除DOM元素:“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建:在初始渲染条件为假时,什么也不做. v-sho ...

  9. pat乙级1059

    1.c++ 位数不够前面补零: printf("04d", i); 位数不够前面补空格(右对齐): printf("4d", i); 位数不够后面补空格(左对齐 ...

  10. [VC]C++ operator 两种用法

    C++中的operator,有两种用法,一种是operator overloading(操作符重载),一种是operator casting(操作隐式转换).下面分别进行介绍:   1.operato ...