.Net 从零开始构建一个框架之基本实体结构与基本仓储构建

本系列文章将介绍如何在.Net框架下,从零开始搭建一个完成CRUD的Framework,该Framework将具有如下功能,基本实体结构(基于DDD)、基本仓储结构、模块加载系统、工做单元、事件总线(EventBus,具备事件溯源的功能)、以及依赖注入管理系统.数据库

 

一、简介app

本文将经过源码和代码注释和文字说明来解释基本实体结构的构建和基本仓储的构建框架

 

二、实战 异步

(1)、基本实体的构建ide

在OOP的概念之下,对象大体能够分为两类,持久化对象和非持久化对象.本文主要讨论的是持久化对象,即须要写入到数据库或者其余数据容器中的对象,也就是实体(固然这里不是所谓的实体,而是经过OOP技术构建出来的一个实体结构,这个结构须要知足平常开发中绝大多数的业务需求).接下去,就是使用OOP技术来构建这个实体结构.优化

首先这个实体既然须要写入数据库,那么它一定有一个主键Id.同时这个主键Id能够是任意数据类型,固然用的最多的就是GUID和INT做为主键.前面全局惟一,后者查询效率快.ui

因此,就有了以下结构:spa

    public interface IEntity<TPrimaryKey>
    {
        /// <summary>
        /// 实体的主键Id
        /// </summary>
        TPrimaryKey Id { get; set; }
    }

其次,以不一样数据类型(GUID、int、string)为主键的实体类型,存在一些共有方法,好比须要编写更加语义化的ToString方法,因此当不一样类型须要共同的实现的时候,这个时候就须要一层抽象,来处理这层关系,因此就有了以下结构:code

  [Serializable]
 public abstract class Entity<TPrimaryKey> : IEntity<TPrimaryKey> { public TPrimaryKey Id { get; set; } /// <summary> /// 返回当前实体的类型名称+Id的形式 /// </summary> /// <returns></returns> public override string ToString() { return $"{GetType().Name} {Id}"; } }

固然这个结构中能够有任何的共有方法,只要它们能成功的抽象出来,就能写入到里面.对象

接着,基本实体就出现了,这里我分为两类,一类以int为主键,一类已Guid主键,为别写道两个类中,以下代码:

    /// <summary>
    /// 以int为主键的实体类型
    /// </summary>
    [Serializable]
    public abstract class Entity: Entity<int>
    {

    }

    /// <summary>
    /// 以Guid为为主键的实体类型
    /// </summary>
    [Serializable]
    public abstract class GEntity : Entity<Guid>
    {

    }

打上Serializable特性,方便序列化.这里不一样的子类使用abstract来实现,也是为了提供各自实体的共有抽象属性(或者方法).到这一步,最最基本的实体抽象构建完毕,可是尚未结束,由于这个结构能够继续优化.使它能够为咱们的业务更好的服务.因此须要持久化的实体一定存在一个建立的过程,可能该实体在某些业务下不须要修改、删除或者查询功能,可是它有极大的几率存在一个建立的过程,因此这里须要构建一个实体建立的抽象类,代码以下:

    public interface ICreationAudited
    {
        /// <summary>
        /// 建立该实体的用户Id
        /// </summary>
        int? CreatorUserId { get; set; }

        /// <summary>
        /// 建立当前实体时的时间
        /// </summary>
        DateTime CreationTime { get; set; }
    }

    [Serializable]
    public abstract class CreationAuditedEntity<TPrimaryKey> : Entity<TPrimaryKey>, ICreationAudited
    {
        public int? CreatorUserId { get; set; }

        public DateTime CreationTime { get; set; }

        /// <summary>
        /// 构造 当前实体注入内存时,给定建立时间,存在偏差,由于从业务点击页面建立到实际生成该实体阶段存在时间差,可是这个时间差能够忽略不计
        /// </summary>
        protected CreationAuditedEntity()
        {
            CreationTime = DateTime.Now;
        }
    }

    /// <summary>
    /// 实体建立      主键为int
    /// </summary>
    [Serializable]     
public abstract class CreationAuditedEntity : CreationAuditedEntity<int> { }

这里考虑文章大小,Guid的实体建立类型就不实现了,接下去只实现int.

最后实体建立的结构,构建完毕以后,在编写一个须要增删查改全部功能都具有的实体结构,整个实体结构大体就构建完毕了,代码以下:

    public interface IDeletionAudited
    {
        /// <summary>
        /// 删除实体的用户Id
        /// </summary>
        int? DeleterUserId { get; set; }

        /// <summary>
        /// 删除实体的时间
        /// </summary>
        DateTime? DeletionTime { get; set; }
    }

    public interface IModificationAudited
    {
        /// <summary>
        /// 最后一次修改实体的用户Id
        /// </summary>
        int? LastModifierUserId { get; set; }

        /// <summary>
        /// 最后一次修改实体的时间
        /// </summary>
        DateTime? LastModificationTime { get; set; }
    }

    public interface IFullAudited : IDeletionAudited, IModificationAudited, ICreationAudited
    {

    }

    [Serializable]
    public abstract class FullAuditedEntity<TPrimaryKey>:CreationAuditedEntity<TPrimaryKey>,IFullAudited
    {
        public int? DeleterUserId { get; set; }

        public DateTime? DeletionTime { get; set; }

        public int? LastModifierUserId { get; set; }

        public DateTime? LastModificationTime { get; set; }
    }

    /// <summary>
    /// 具备增删查该功能的实体结构 主键为int
    /// </summary>
    public abstract class FullAuditedEntity : FullAuditedEntity<int>
    {

    }

ok,到这里基本的实体结构构建完毕,固然这里你能够随意的扩展,好比构建各类各样的默认的实体类,如主键为string的只具备修改和删除的实体类.能够根据业务的实体特性来动态的扩展.也能够向全部的抽象实体类中添加任意的抽象属性或者方法.好比给Entity添加获取HashCode的共有方法.

 

(2)、基本仓储结构的构建

关于仓储就很少介绍了,能够自行上网查阅相关的文章,基本仓储结构是依赖于实体结构的。本文将基本Dapper构建一套基本仓储结构.

首先必须有一个仓储接口标识,这个标识自己不具备方法,单单只是一个标识,方便后期实现工做单元和模块加载系统时,辨别出程序集中的仓储类型.以下:

    /// <summary>
    /// 仓储接口
    /// </summary>
    public interface IRepository
    {

    }

接着,基于这个接口来构建Dapper通用仓储具备的基本的功能,即增删查改、分页、列表等功能.代码以下:

    /// <summary>
    /// Dapper通用仓储接口
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <typeparam name="TPrimaryKey"></typeparam>
    public interface IDapperRepository<TEntity, TPrimaryKey> : IRepository where TEntity : class, IEntity<TPrimaryKey>
    {
        /// <summary>
        /// 添加一条实体信息
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        Task InsertAsync(TEntity entity);

        /// <summary>
        /// 删除一条实体信息
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        Task DeleteAsync(TEntity entity);

        /// <summary>
        /// 修改一条实体信息
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        Task UpdateAsync(TEntity entity);

        /// <summary>
        /// 根据主键Id异步获取一条数据信息
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        Task<TEntity> GetAsync(TPrimaryKey id);


    }
相关文章
相关标签/搜索