基于abp vnext手动编写一个功能的完整步骤

        本文忽略对abp vnext框架及DDD软件开发方法的解析,直入主题,讲解一个功能实现中各层代码的实现,步骤如下:

        1、下载模块框架代码

        通过使用 abp cli或者直接通过官方进行下载,如下图:

2、领域层定义

领域层划分为两个项目:

  • Domain.Shared 包(项目) 命名为CompanyName.ModuleName.Domain.Shared,包含常量,枚举和其他类型, 它不能包含实体,存储库,域服务或任何其他业务对象. 可以安全地与模块中的所有层使用. 此包也可以与第三方客户端使用.
  • Domain 包(项目) 命名为CompanyName.ModuleName.Domain, 包含实体, 仓储接口,领域服务接口及其实现和其他领域对象.
    • Domain 包依赖于 Domain.Shared 包.

1)实体定义

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;

namespace demo1.Articles
{
    /// <summary>
    /// 文章
    /// </summary>
    public class Article : CreationAuditedEntity<Guid>, IMultiTenant
    {
        /// <summary>
        /// 租户Id
        /// </summary>
        public Guid? TenantId { get; private set; }

        /// <summary>
        /// 标题
        /// </summary>
        /// <returns></returns>
        [Required]
        [MaxLength(100)]
        public string Title { get; set; }

        /// <summary>
        /// 副标题
        /// </summary>
        /// <returns></returns>
        [MaxLength(100)]
        public string SubTitle { get; set; }

        /// <summary>
        /// 作者
        /// </summary>
        /// <returns></returns>
        [MaxLength(50)]
        public string Aauthor { get; set; }

        /// <summary>
        /// 内容
        /// </summary>
        /// <returns></returns>
        [Required]
        public string Content { get; set; }

        /// <summary>
        /// 来源
        /// </summary>
        public string Source { get; set; }

    }
}

2)仓储接口

一般存放在与实体定义在同一个文件夹下,命名约定为:I{实体名}Repositor,如:IArticleRepository。

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using Volo.Abp.Domain.Repositories;

namespace demo1.Articles
{
    /// <summary>
    /// 文章 仓储接口
    /// </summary>
    public interface IArticleRepository : IRepository<Article, Guid>
    {
        Task<List<Article>> GetListAsync(
           bool paged = true,
           string sorting = null,
           int maxResultCount = int.MaxValue,
           int skipCount = 0,
           string filter = null,
           CancellationToken cancellationToken = default
       );

        Task<long> GetCountAsync(
            string filter = null,
            CancellationToken cancellationToken = default);
    }
}

 3、基础设施层的代码变动

  • 推荐 为每个orm/数据库集成创建一个独立的集成包, 比如Entity Framework Core 和 MongoDB.
    • 推荐 例如, 创建一个抽象Entity Framework Core集成的CompanyName.ModuleName.EntityFrameworkCore 包. ORM 集成包依赖于 Domain 包.
    • 不推荐 依赖于orm/数据库集成包中的其他层.
  • 推荐 为每个主要的库创建一个独立的集成包, 在不影响其他包的情况下可以被另一个库替换.

 

 

using demo1.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;

namespace demo1.Articles
{
    public class ArticleRepository : EfCoreRepository<Idemo1DbContext, Article, Guid>, IArticleRepository
    {
        public ArticleRepository(IDbContextProvider<Idemo1DbContext> dbContextProvider) : base(dbContextProvider)
        {
        }

        public virtual async Task<List<Article>> GetListAsync(
            bool paged = true,
            string sorting = null,
            int maxResultCount = int.MaxValue,
            int skipCount = 0,
            string filter = null,
            CancellationToken cancellationToken = default
        )
        {
            var query = (await GetDbSetAsync())
                .WhereIf(
                    !filter.IsNullOrWhiteSpace(),
                    u => u.Title.Contains(filter)
                    )
                .OrderBy(sorting.IsNullOrWhiteSpace() ? "CreationTime desc" : sorting);

            if (paged)
            {
                return await query.PageBy(skipCount, maxResultCount).ToListAsync(GetCancellationToken(cancellationToken));
            }
            else
            {
                return await query.ToListAsync(GetCancellationToken(cancellationToken));
            }
        }

        public virtual async Task<long> GetCountAsync(
            string filter = null,
            CancellationToken cancellationToken = default)
        {
            return await (await GetDbSetAsync())
                .WhereIf(
                    !filter.IsNullOrWhiteSpace(),
                    u => u.Title.Contains(filter)
                    )
                .LongCountAsync(GetCancellationToken(cancellationToken));
        }
    }
}

4、应用服务层的代码变动

将应用服务层划分为两个项目:

  • Application.Contracts 包(项目) 命名为*CompanyName.ModuleName.Application.Contracts,包含应用服务接口和相关的数据传输对象(DTO).
    • Application contract 包依赖于 Domain.Shared 包.
  • Application 包(项目)命名为CompanyName.ModuleName.Application,包含应用服务实现.
    • Application 包依赖于 Domain 包和 Application.Contracts 包.

 

 

5、数据库迁移 

使用add-migration 和Update-Database进行数据库迁移。

总结:每个领域功能的开发流程大致如此。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NetX行者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值