- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
@ 。
在常见的业务系统中,对数据的大部分操作都是Curd,在实践的过程中对数据的筛选、排序、分页、关联查询等功能抽象和封装.
本系列博文将从0开始,逐步搭建一个基于Volo.Abp + Vue 的前后端分离的,具有Curd通用查询功能的项目.
怎样优雅地增删查改(一):从0开始搭建Volo.Abp项目 。
怎样优雅地增删查改(二):扩展身份管理模块 。
本项目是基于一个简单的用户健康数据管理系统,我们将对业务常用的查询功能进行扩展,抽象这些业务并封装成接口,称之为通用查询接口(GeneralCurdInterfaces),本项目关注的是基础设施层,但大部分实现还是围绕业务,对于普适性有待研究,所以我还是决定以Sample为名.
Abp模块是可以供主模块重用的独立功能单元,每个模块可以包含应用服务、领域层、数据访问层、Web API等,模块可以被其他模块引用,也可以被主模块引用.
本项目模块化的目的除了可重用,更多是为微服务架构做准备。微服务架构不在本博文的讨论范围,为了简化,还是使用单体应用架构.
Volo.Abp 为我们实现了 CrudAppService ,(在旧版本的AbpBoilerplate中称Crud为Curd,在我看来两者没有什么区别,本项目还是以Curd命名) 。
CrudAppService 为我们提供了基本的增删改查,以及分页、排序的实现 。
按任意字段关键字查询 。
按任意字段排序 。
按组织架构查询 。
按用户查询 。
按用户关系查询 。
按创建日期查询(起始日期,结束日期) 。
本项目虽然是用Volo.Abp实现,但对于旧版本的AbpBoilerplate仍然可以方便的移植,可以看我之前的博文: [Volo.Abp升级笔记]使用旧版Api规则替换RESTful Api以兼容老程序 ,如何以最大限度保持接口的兼容性.
创建空白文件夹,在文件夹内打开命令行 。
使用 AbpCli 创建一个无UI的项目 拆分Auth Server,执行以下命令 。
abp new Matoapp -u none --separate-auth-server -csf
等待项目创建成功 。
作为命名空间前缀,Matoapp是一个虚构的企业名称.
在解决方案目录中创建新目录 src/modules ,在该目录下创建员工健康管理模块Health,公共业务模块Common,以及扩展了Volo.Abp.Indentity的Identity模块 。
在modules目录下打开命令行,分别执行以下命令 。
abp new Matoapp.Health -t module --no-ui
abp new Matoapp.Common -t module --no-ui
abp new Matoapp.Identity -t module --no-ui
等待模块创建完成 。
打开解决方案,将业务模块中的各个项目添加到解决方案中,我们只需要添加各模块的 Application , Application.Contracts , Domain , Domain.Shared , EntityFrameworkCore , HttpApi 以及 HttpApi.Client .
添加完成后的解决方案结构看上去像这样:
将 Volo.Abp.Identity.Application 添加到Application项目的引用中 。
dotnet add package Volo.Abp.Identity.Application
将 Volo.Abp.Identity.Application.Contracts 添加到Application.Contracts项目的引用中 。
dotnet add package Volo.Abp.Identity.Application.Contracts
将 Volo.Abp.Identity.Domain , Volo.Abp.PermissionManagement.Domain 添加到Domain项目的引用中 。
dotnet add package Volo.Abp.Identity.Domain
dotnet add package Volo.Abp.PermissionManagement.Domain
将 Volo.Abp.Identity.EntityFrameworkCore 添加到EntityFrameworkCore项目的引用中 。
dotnet add package Volo.Abp.Identity.EntityFrameworkCore
Application层 。
Application层添加对各模块的引用, ApplicationModule中添加对各模块的依赖 。
[DependsOn(
...
typeof(CommonApplicationModule),
typeof(HealthApplicationModule),
typeof(IdentityApplicationModule)
)]
public class MatoappApplicationModule : AbpModule
{
}
AuthServer添加Identity数据访问层引用,并配置依赖关系 。
[DependsOn(
...
typeof(IdentityDomainModule),
typeof(IdentityEntityFrameworkCoreModule)
)]
public class MatoappAuthServerModule : AbpModule
{
}
HttpApi层添加对各模块的引用, HttpApiModule中添加对各模块的依赖 。
[DependsOn(
...
typeof(CommonHttpApiModule),
typeof(HealthHttpApiModule),
typeof(IdentityHttpApiModule)
)]
public class MatoappHttpApiModule : AbpModule
{
}
用CodeFirst方式创建一些业务表,比如员工表,客户表,报警表等,这些表都是在Health模块中创建的, 。
Tag相关的表放入Common模块中,Relation表放入Identity模块中.
这些业务表按照业务模块的划分,放入各自的DbContext中.
public interface IIdentityDbContext : IEfCoreDbContext
{
DbSet<Relation.Relation> Relation { get; set; }
}
public interface IHealthDbContext : IEfCoreDbContext
{
DbSet<Client.Client> Client { get; set; }
DbSet<Employee.Employee> Employee { get; set; }
DbSet<Alarm.Alarm> Alarm { get; set; }
DbSet<SimpleValueRecord> SimpleValueRecord { get; set; }
}
public interface ICommonDbContext : IEfCoreDbContext
{
DbSet<DataEnum.DataEnum> DataEnum { get; set; }
DbSet<DataEnumCategory.DataEnumCategory> DataEnumCategory { get; set; }
DbSet<Tag.Tag> Tag { get; set; }
}
各业务模块的DbContextModelCreatingExtensions中添加对各表的字段,约束,索引等的配置。以便在DbContext的OnModelCreating中调用 。
builder.ConfigureCommon();
builder.ConfigureHealth();
builder.ConfigureMatoIdentity();
EntityFrameworkCore层中改写MatoappDbContext如下:
[ReplaceDbContext(typeof(Matoapp.Identity.EntityFrameworkCore.IIdentityDbContext))]
[ReplaceDbContext(typeof(IHealthDbContext))]
[ReplaceDbContext(typeof(ICommonDbContext))]
[ReplaceDbContext(typeof(ITenantManagementDbContext))]
[ConnectionStringName("Default")]
public class MatoappDbContext :
AbpDbContext<MatoappDbContext>,
Matoapp.Identity.EntityFrameworkCore.IIdentityDbContext,
IHealthDbContext,
ICommonDbContext,
ITenantManagementDbContext
{
#region Entities from the modules
public DbSet<Relation> Relation { get; set; }
// Tenant Management
public DbSet<Tenant> Tenants { get; set; }
public DbSet<TenantConnectionString> TenantConnectionStrings { get; set; }
public DbSet<Client> Client { get; set; }
public DbSet<Employee> Employee { get; set; }
public DbSet<Alarm> Alarm { get; set; }
public DbSet<SimpleValueRecord> SimpleValueRecord { get; set; }
public DbSet<DataEnum> DataEnum { get; set; }
public DbSet<DataEnumCategory> DataEnumCategory { get; set; }
public DbSet<Tag> Tag { get; set; }
#endregion
public MatoappDbContext(DbContextOptions<MatoappDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
/* Include modules to your migration db context */
builder.ConfigurePermissionManagement();
builder.ConfigureSettingManagement();
builder.ConfigureBackgroundJobs();
builder.ConfigureAuditLogging();
builder.ConfigureIdentity();
builder.ConfigureOpenIddict();
builder.ConfigureFeatureManagement();
builder.ConfigureTenantManagement();
builder.ConfigureCommon();
builder.ConfigureHealth();
builder.ConfigureMatoIdentity();
/* Configure your own tables/entities inside here */
//builder.Entity<YourEntity>(b =>
//{
// b.ToTable(MatoappConsts.DbTablePrefix + "YourEntities", MatoappConsts.DbSchema);
// b.ConfigureByConvention(); //auto configure for the base class props
// //...
//});
}
}
在AuthServer创建AuthServerDbContextFactory,AuthServerDbContext.
AuthServerDbContext.cs代码如下 。
public class AuthServerDbContext : AbpDbContext<AuthServerDbContext>
{
public AuthServerDbContext(DbContextOptions<AuthServerDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.ConfigureIdentity();
modelBuilder.ConfigureIdentityServer();
modelBuilder.ConfigureAuditLogging();
modelBuilder.ConfigurePermissionManagement();
modelBuilder.ConfigureSettingManagement();
modelBuilder.ConfigureTenantManagement();
modelBuilder.ConfigureFeatureManagement();
modelBuilder.ConfigureMatoIdentity();
}
}
在各业务模块中创建实体类,以及对应的Dto类 此处以Health模块为例,创建以下实体类 。
根据实际业务需求,配置AutoMapper,将实体类映射到DTO类。此处以Health模块为例.
public HealthApplicationAutoMapperProfile()
{
CreateMap<Client.Client, ClientDto>().Ignore(c => c.EntityVersion);
CreateMap<Employee.Employee, EmployeeDto>().Ignore(c => c.EntityVersion);
CreateMap<ClientDto, Client.Client>();
CreateMap<EmployeeDto, Employee.Employee>();
CreateMap<Alarm.Alarm, AlarmDto>();
CreateMap<Alarm.Alarm, AlarmBriefDto>();
CreateMap<AlarmDto, Alarm.Alarm>().Ignore(c => c.TenantId)
.Ignore(c => c.ConcurrencyStamp);
CreateMap<CreateAlarmInput, Alarm.Alarm>().IgnoreFullAuditedObjectProperties()
.IgnoreSoftDeleteProperties()
.Ignore(c => c.TenantId)
.Ignore(c => c.User)
.Ignore(c => c.ConcurrencyStamp)
.Ignore(c => c.Id);
CreateMap<UpdateAlarmInput, Alarm.Alarm>().IgnoreFullAuditedObjectProperties()
.IgnoreSoftDeleteProperties()
.Ignore(c => c.TenantId)
.Ignore(c => c.User)
.Ignore(c => c.ConcurrencyStamp);
CreateMap<SimpleValueRecord, SimpleValueRecordBriefDto>();
CreateMap<SimpleValueRecord, SimpleValueRecordDto>();
CreateMap<SimpleValueRecordDto, SimpleValueRecord>().Ignore(c => c.TenantId)
.Ignore(c => c.Alarm)
.Ignore(c => c.ConcurrencyStamp);
CreateMap<CreateClientInput, Client.Client>()
.ForAllMembers(opt => opt.Condition((src, dest, srcMember, destMember) => srcMember != null));
CreateMap<CreateClientWithUserInput, Client.Client>()
.IgnoreFullAuditedObjectProperties()
.IgnoreSoftDeleteProperties()
.Ignore(c => c.LockoutEnabled)
.Ignore(c => c.LockoutEnd)
.Ignore(c => c.TenantId)
.Ignore(c => c.ConcurrencyStamp)
.Ignore(c => c.EmailConfirmed)
.Ignore(c => c.PhoneNumberConfirmed)
.Ignore(c => c.Id)
.ForAllMembers(opt => opt.Condition((src, dest, srcMember, destMember) => srcMember != null));
CreateMap<CreateEmployeeInput, Employee.Employee>()
.ForAllMembers(opt => opt.Condition((src, dest, srcMember, destMember) => srcMember != null));
CreateMap<CreateEmployeeWithUserInput, Employee.Employee>()
.IgnoreFullAuditedObjectProperties()
.IgnoreSoftDeleteProperties()
.Ignore(c => c.LockoutEnabled)
.Ignore(c => c.LockoutEnd)
.Ignore(c => c.TenantId)
.Ignore(c => c.ConcurrencyStamp)
.Ignore(c => c.EmailConfirmed)
.Ignore(c => c.PhoneNumberConfirmed)
.Ignore(c => c.Id)
.ForAllMembers(opt => opt.Condition((src, dest, srcMember, destMember) => srcMember != null));
}
至此,我们有了基础的数据库,实体类,Dto类。下一步我们将创建通用Curd应用服务,以及通用查询接口.
最后此篇关于怎样优雅地增删查改(一):从0开始搭建Volo.Abp项目的文章就讲到这里了,如果你想了解更多关于怎样优雅地增删查改(一):从0开始搭建Volo.Abp项目的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我刚刚开始探索 Abp 功能,我从他们的网站创建了一个示例项目并能够成功构建该项目。但是当我运行 dbmigrator 项目时出现异常,下面是错误的截图, 我按照这篇文章运行了应用 https://d
我正在尝试使用 abp.framework(版本 3)为 Entity Framework 数据库播种和 AppUser。我知道如何使用 IdentityUserManager 为 IdentityU
我使用具有商业许可的 abp 套件生成了一个 MVC 项目。它有默认的 Lepton 主题,但我想切换到基本主题,因为它更容易定制。 最佳答案 安装 Volo.Abp.AspNetCore.Mvc.U
我使用具有商业许可的 abp 套件生成了一个 MVC 项目。它有默认的 Lepton 主题,但我想切换到基本主题,因为它更容易定制。 最佳答案 安装 Volo.Abp.AspNetCore.Mvc.U
在我的公司,我们使用全新的 Abp 框架 (abp.io)。由于它是一个新框架,因此缺少很多文档,因此我们必须搜索源代码。看了这么多代码,我意识到这是他们使用的模式,总是出现 Providers、Pr
前言 对于大多数.NET后端开发者而言,ABP框架已经相当熟悉,可以轻松进行二次开发,无需重复实现用户角色管理、权限控制、组织管理和多租户等功能。 然而,ABP框架主要专注于Web应用,对于桌面端
1. 事件总线 在我们的一个应用中,经常会出现一个逻辑执行之后要跟随执行另一个逻辑的情况,例如一个用户创建了后续还需要发送邮件进行通知,或者需要初始化相应的权限等。面对这样的情况,我们当然可以
ABP框架 ABP是用于创建现代化Web应用程序的完整体系结构和强大的基础架构,以模块化的方式进行开发,所有模块以nuget包的方式提供,开箱即用,遵循最佳实践和约定,提供 SOLID 开
Abp是一个基于模块化开发的应用程序框架,提供了模块化基础的架构和模块化加载的引擎。 理解模块 一个模块是对一个功能点的封装,可以独立成为一个包,实现了松耦合的代码组织方式。A
Abp.NHibernate动态库连接PostgreSQl数据库,供大家参考,具体内容如下 初次接触Abp框架,其框架中封装的操作各类数据的方法还是很好用的,本人还在进一步的学习当中,并将利用ab
前言 Volo.Abp.VirtualFileSystem 是ABP(ASP.NET Boilerplate)框架中的一个重要组件,它提供了一种抽象文件系统的方式,使得应用程序可以轻松地访问和管理文
在apb-vnext的实体的创建中可以确实字段的长度、说明、对应的表、表中给字段加的索引 以项目中的订单表为例,如下: [Comment("订单主表")] [Tabl
我不能完全理解在什么情况下我会使用 DomainService 和在这种情况下你的文件不详细在这个问题上足够了。你能给出更详细的解释吗举个例子? 如果我只使用 ApplicationService 而
1. 缓存模块源码解析 个人觉得 ABP 分布式缓存模块有三个值得关注的核心点。首先是 AbpRedisCache 类继承了微软原生的 RedisCache,并 通过反射的方式获取RedisC
依赖注入的使用 构造方法注入 这是将服务注入类的最常用方法,是将依赖项注入类的首选方式,也是微软推崇的模式。这样,除非提供了所有构造方法注入的依赖项,否则无法构造类,显示的声明了类必需的服
1. 与 .NET Core 缓存的关系和差异 ABP 框架中的缓存系统核心包是 Volo.Abp.Caching ,而对于分布式缓存的支持,abp 官方提供了基于 Redis 的方案,需要安装
依赖注入实现了系统之间、模块之间和对象之间依赖关系的解耦,基本上是现代应用程序框架必不可少的一个组成部分。 ABP的依赖注入系统是基于Microsoft的依赖注入扩展库(Microso
默认情况下,AbpUserRole 和AbpRole 实现ISoftDelete。是否可以禁用它? 我试着这样做: [AbpAuthorize(AppPermissions.Pages_Adminis
默认情况下,AbpUserRole 和AbpRole 实现ISoftDelete。是否可以禁用它? 我试着这样做: [AbpAuthorize(AppPermissions.Pages_Adminis
我在构建网站时了解到客户想要 2 个 300x250 的广告和 1 个 728x90 的广告。我已经使用以下 HTML 将这些添加到设计中: 这很好用。我添加
我是一名优秀的程序员,十分优秀!