学习ASP.NET Core(03)-数据层逻辑层与模型转换

上一篇我们使用Code First的方式完成了数据库的建立 ,本章我们来完善一下数据访问层和业务逻辑层部分的内容


一、IDAL与DAL

根据依赖倒置原则,细节应该依赖于抽象,我们我们要针对抽象,即面向接口进行编程,其好处是解耦和利于重构

1、IDAL实现

1.1、基类接口

这里添加一个CURD操作的基类接口,名为IBaseRepository,其余每个model都对应一个接口并继承该基类接口。在这之前IDAL层需要添加对Model层的引用。如下:

using System;
using System.Linq;
using System.Threading.Tasks;
using BlogSystem.Model;

namespace BlogSystem.IDAL
{
    /// <summary>
    /// 基类接口
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    public interface IBaseRepository<TEntity> where TEntity : BaseEntity
    {
        /// <summary>
        /// 新增数据
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="saved"></param>
        /// <returns></returns>
        Task CreateAsync(TEntity entity, bool saved = true);

        /// <summary>
        /// 根据Id删除数据
        /// </summary>
        /// <param name="id"></param>
        /// <param name="saved"></param>
        /// <returns></returns>
        Task RemoveAsync(Guid id, bool saved = true);

        /// <summary>
        /// 根据model删除对数据
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="saved"></param>
        /// <returns></returns>
        Task RemoveAsync(TEntity entity, bool saved = true);

        /// <summary>
        /// 修改数据
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="saved"></param>
        /// <returns></returns>
        Task EditAsync(TEntity entity, bool saved = true);

        /// <summary>
        /// 通过Id查询数据
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        Task<TEntity> GetOneByIdAsync(Guid id);

        /// <summary>
        /// 获取所有数据
        /// </summary>
        /// <returns></returns>
        IQueryable<TEntity> GetAll();

        /// <summary>
        /// 获取所有数据并排序
        /// </summary>
        /// <returns></returns>
        IQueryable<TEntity> GetAllByOrder(bool asc = true);

        /// <summary>
        /// 统一保存方法
        /// </summary>
        /// <returns></returns>
        Task SavedAsync();

        /// <summary>
        /// 判断对象是否存在
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        Task<bool> Exists(Guid id);
    }
}

1.2、其余接口

其余的每个model也都定义一个接口并继承IBaseRepository,给出一个示例,其余需要一一对应如下:

using BlogSystem.Model;

namespace BlogSystem.IDAL
{
    public interface IArticleRepository : IBaseRepository<Article>
    {
    }
}


2、DAL实现

2.1、基类方法

首先DAL层需要添加对Model层和DAL层的引用,然后我们在DAL项目下添加一个名为BaseRepository的类,并继承基类接口IBaseRepository,添加泛型约束泛型参数为BlogSystem.Model中的BaseEntity,实现如下:

using System;
using System.Linq;
using System.Threading.Tasks;
using BlogSystem.IDAL;
using BlogSystem.Model;
using Microsoft.EntityFrameworkCore;

namespace BlogSystem.DAL
{
    /// <summary>
    /// 实现基类接口
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    public class BaseRepository<TEntity> : IBaseRepository<TEntity> where TEntity : BaseEntity, new()
    {
        private readonly BlogSystemContext _context;

        public BaseRepository(BlogSystemContext context)
        {
            _context = context;
        }

        /// <summary>
        /// 新增数据
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="saved"></param>
        /// <returns></returns>
        public async Task CreateAsync(TEntity entity, bool saved = true)
        {
            _context.Set<TEntity>().Add(entity);
            if (saved) await _context.SaveChangesAsync();
        }

        /// <summary>
        /// 根据Id删除数据
        /// </summary>
        /// <param name="id"></param>
        /// <param name="saved"></param>
        /// <returns></returns>
        public async Task RemoveAsync(Guid id, bool saved = true)
        {
            var t = new TEntity() { Id = id };
            _context.Entry(t).State = EntityState.Unchanged;
            t.IsRemoved = true;
            if (saved) await _context.SaveChangesAsync();
        }

        /// <summary>
        /// 根据model删除数据
        /// </summary>
        /// <param name="model"></param>
        /// <param name="saved"></param>
        /// <returns></returns>
        public async Task RemoveAsync(TEntity model, bool saved = true)
        {
            await RemoveAsync(model.Id, saved);
        }

        /// <summary>
        ///  修改数据
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="saved"></param>
        /// <returns></returns>
        public async Task EditAsync(TEntity entity, bool saved = true)
        {
            _context.Entry(entity).State = EntityState.Modified;

            //如果数据没有发生变化
            if (!_context.ChangeTracker.HasChanges()) return;

            if (saved) await _context.SaveChangesAsync();
        }

        /// <summary>
        /// 通过Id查询数据
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<TEntity> GetOneByIdAsync(Guid id)
        {
            return await GetAll().FirstOrDefaultAsync(m => m.Id == id);
        }

        /// <summary>
        /// 获取所有数据
        /// </summary>
        /// <returns></returns>
        public IQueryable<TEntity> GetAll()
        {
            return _context.Set<TEntity>().Where(m => !m.IsRemoved).AsNoTracking();
        }

        /// <summary>
        /// 获取所有数据并排序
        /// </summary>
        /// <returns></returns>
        public IQueryable<TEntity> GetAllByOrder(bool asc = true)
        {
            var data = GetAll();
            data = asc ? data.OrderBy(m => m.CreateTime) : data.OrderByDescending(m => m.CreateTime);
            return data;
        }

        /// <summary>
        /// 统一保存方法
        /// </summary>
        /// <returns></returns>
        public async Task SavedAsync()
        {
            await _context.SaveChangesAsync();
        }

        /// <summary>
        /// 确认对象是否存在
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<bool> Exists(Guid id)
        {
            return await GetAll().AnyAsync(m => m.Id == id);
        }
    }
}

2.2、其余方法

其余IDAL中的接口采用继承的方式实现,给出一个示例,其余同理,如下:

    public class ArticleCommentRepository : BaseRepository<ArticleComment>, IArticleCommentRepository
    {
        public ArticleCommentRepository() : base(new BlogSystemContext(new DbContextOptions<BlogSystemContext>()))
        {
        }
    }


二、模型对象

1、概念

在DAL层我们是对数据库的直接操作,面向的也是我们设计的包含属性的model;但在BLL层,面向的是业务逻辑,业务逻辑对应的是用户的操作,在软件的实际使用过程中,用户看到的页面并非对应一个完整的model,页面可能是model的一部分,也有可能由几个model的一部分组合而成的。为了解决这类问题,我们通常使用模型对象

2、常用的两种模型对象

1、Dto(Data Transfer Object):又名数据传输对象,常用来定义包含属性的实体类,它只引用基本数据类型,不引用对象类型,且没有行为,它只专注于数据本身,一般用于DAL和BLL之间的数据传输;

2、ViewModel:又名视图模型,它根据View创建,是View的数据容器,它专注的是View,用来呈现给用户,它由一个或多个Dto的组成;

3、实际应用

根据上面的描述,DAL与BLL层的数据交互我们应该使用Dto对象,呈现给页面时需要使用ViewModel对应,但在实际的开发中,Dto与ViewModel重合度很高,所以部分开发者只使用一种,但兼并两类角色。此外,Model与Dto/ViewModel之间的转换,我们可以使用EF的Select方法进行投影解决,或者使用AutoMapper之类的插件。

三、IBLL与ViewModel

这里我们根据功能大类,分为用户,文章、分类和评论,所以在IBLL中我们暂时先添加这4个接口, 在这之前需要添加对Model层的引用。根据实体对象部分的讲述,我们在Model层添加一个ViewModels文件夹,里面用来放置ViewModel对象,ViewModel对象属性通常会使用一些特性限制用户的录入。

1、基类接口

我们发现可以提取出常用的几个方法,避免重复代码,操作如下:

using BlogSystem.Model;
using System;
using System.Threading.Tasks;

namespace BlogSystem.IBLL
{
    /// <summary>
    /// 基类服务接口
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    public interface IBaseService<TEntity> where TEntity : BaseEntity
    {
        /// <summary>
        /// 根据Id删除实体
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        Task RemoveAsync(Guid id);

        /// <summary>
        /// 删除实体
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        Task RemoveAsync(TEntity entity);

        /// <summary>
        /// 通过Id查询实体
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        Task<TEntity> GetOneByIdAsync(Guid id);

        /// <summary>
        /// 判断实体是否存在
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        Task<bool> ExistsAsync(Guid id);
    }
}

2、文章接口与ViewModel

1、在Model层的ViewModel中添加相关的ViewModel,即用户所视内容需要用到的属性

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace BlogSystem.Model.ViewModels
{
    /// <summary>
    /// 创建文章
    /// </summary>
    public class CreateArticleViewModel
    {
        /// <summary>
        /// 创建用户Id
        /// </summary>
        public Guid UserId { get; set; }

        /// <summary>
        /// 文章标题
        /// </summary>
        [Required]
        public string Title { get; set; }

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

        /// <summary>
        /// 文章分类
        /// </summary>
        public List<Guid> CategoryIds { get; set; }
    }
}
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace BlogSystem.Model.ViewModels
{
    /// <summary>
    /// 编辑文章
    /// </summary>
    public class EditArticleViewModel
    {
        /// <summary>
        /// 文章Id
        /// </summary>
        public Guid Id { get; set; }

        /// <summary>
        /// 文章标题
        /// </summary>
        [Required]
        public string Title { get; set; }

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

        /// <summary>
        /// 文章分类
        /// </summary>
        public List<Guid> CategoryIds { get; set; }
    }
}
using System;

namespace BlogSystem.Model.ViewModels
{
    /// <summary>
    /// 文章列表
    /// </summary>
    public class ArticleListViewModel
    {
        /// <summary>
        /// 文章Id
        /// </summary>
        public Guid ArticleId { get; set; }

        /// <summary>
        /// 文章标题
        /// </summary>
        public string Title { get; set; }

        /// <summary>
        /// 文章内容
        /// </summary>
        public string Content { get; set; }

        /// <summary>
        /// 创建时间
        /// </summary>
        public DateTime CreateTime { get; set; }

        /// <summary>
        /// 账号
        /// </summary>
        public string Account { get; set; }

        /// <summary>
        /// 头像
        /// </summary>
        public string ProfilePhoto { get; set; }
    }
}
using System;
using System.Collections.Generic;

namespace BlogSystem.Model.ViewModels
{
    /// <summary>
    /// 文章详情
    /// </summary>
    public class ArticleDetailsViewModel
    {
        /// <summary>
        /// 文章Id
        /// </summary>
        public Guid Id { get; set; }

        /// <summary>
        /// 文章标题
        /// </summary>
        public string Title { get; set; }

        /// <summary>
        /// 文章内容
        /// </summary>
        public string Content { get; set; }

        /// <summary>
        /// 创建时间
        /// </summary>
        public DateTime CreateTime { get; set; }

        /// <summary>
        /// 作者
        /// </summary>
        public string Account { get; set; }

        /// <summary>
        /// 头像
        /// </summary>
        public string ProfilePhoto { get; set; }

        /// <summary>
        /// 分类Id
        /// </summary>
        public List<Guid> CategoryIds { get; set; }

        /// <summary>
        /// 分类名称
        /// </summary>
        public List<string> CategoryNames { get; set; }

        /// <summary>
        /// 看好人数
        /// </summary>
        public int GoodCount { get; set; }
        /// <summary>
        /// 不看好人数
        /// </summary>
        public int BadCount { get; set; }

    }
}

2、接口实现:IArticleService继承基类接口,并添加如下方法:

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using BlogSystem.Model;
using BlogSystem.Model.ViewModels;

namespace BlogSystem.IBLL
{
    /// <summary>
    /// 文章接口
    /// </summary>
    public interface IArticleService : IBaseService<Article>
    {
        /// <summary>
        /// 新增文章
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        Task CreateArticleAsync(CreateArticleViewModel model);

        /// <summary>
        /// 编辑文章
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        Task EditArticleAsync(EditArticleViewModel model);

        /// <summary>
        /// 通过Id获取文章详情
        /// </summary>
        /// <param name="articleId"></param>
        /// <returns></returns>
        Task<ArticleDetailsViewModel> GetArticleDetailsByArticleIdAsync(Guid articleId);

        /// <summary>
        /// 通过用户Id获取文章列表
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        Task<List<ArticleListViewModel>> GetArticlesByUserIdAsync(Guid userId);

        /// <summary>
        /// 通过分类Id获取所有文章
        /// </summary>
        /// <param name="categoryId"></param>
        /// <returns></returns>
        Task<List<ArticleListViewModel>> GetArticlesByCategoryIdAsync(Guid categoryId);

        /// <summary>
        /// 通过用户Id获取文章数量
        /// </summary>
        /// <param name="userid"></param>
        /// <returns></returns>
        Task<int> GetArticleCountByUserIdAsync(Guid userid);

        /// <summary>
        /// 点赞文章
        /// </summary>
        /// <param name="articleId"></param>
        /// <returns></returns>
        Task AddGoodCount(Guid articleId);

        /// <summary>
        /// 点灭文章
        /// </summary>
        /// <param name="articleId"></param>
        /// <returns></returns>
        Task AddBadCount(Guid articleId);
    }
}

3、分类接口与ViewModel

1、在Model层的ViewMode文件夹中添加相关的ViewModel

using System;
using System.ComponentModel.DataAnnotations;

namespace BlogSystem.Model.ViewModels
{
    public class CreateOrEditCategoryViewModel
    {
        /// <summary>
        /// 分类名称
        /// </summary>
        [Required]
        public string CategoryName { get; set; }

        /// <summary>
        /// 创建用户Id
        /// </summary>
        public Guid UserId { get; set; }
    }
}
namespace BlogSystem.Model.ViewModels
{
    public class CategoryListViewModel
    {
        /// <summary>
        /// 分类名称
        /// </summary>
        public string CategoryName { get; set; }
    }
}

2、分类接口:继承基类接口,并添加如下方法:

using BlogSystem.Model;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using BlogSystem.Model.ViewModels;

namespace BlogSystem.IBLL
{
    /// <summary>
    /// 分类服务接口
    /// </summary>
    public interface ICategoryService : IBaseService<Category>
    {
        /// <summary>
        /// 创建分类
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        Task CreateCategory(CreateOrEditCategoryViewModel model);

        /// <summary>
        /// 编辑分类
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        Task EditCategory(CreateOrEditCategoryViewModel model);

        /// <summary>
        /// 通过用户Id获取所有分类
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        Task<List<CategoryListViewModel>> GetCategoryByUserIdAsync(Guid userId);
    }
}

4、用户接口与ViewModel

1、在Model层的ViewModel文件夹中添加相关的ViewModel

using System;
using System.ComponentModel.DataAnnotations;

namespace BlogSystem.Model.ViewModels
{
    /// <summary>
    /// 用户注册
    /// </summary>
    public class RegisterViewModel
    {
        /// <summary>
        /// 账号
        /// </summary>
        [Required]
        public string Account { get; set; }

        /// <summary>
        /// 密码
        /// </summary>
        [Required]
        public string Password { get; set; }

        /// <summary>
        /// 确认密码
        /// </summary>
        [Required]
        public string RequirePassword { get; set; }
    }
}
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

namespace BlogSystem.Model.ViewModels
{
    /// <summary>
    /// 用户登录
    /// </summary>
    public class LoginViewModel
    {
        /// <summary>
        /// 账号
        /// </summary>
        [Required]
        public string Account { get; set; }

        /// <summary>
        /// 密码
        /// </summary>
        [Required]
        public string Password { get; set; }
    }
}

using System;
using System.ComponentModel.DataAnnotations;

namespace BlogSystem.Model.ViewModels
{
    /// <summary>
    /// 修改用户密码
    /// </summary>
    public class ChangePwdViewModel
    {
        /// <summary>
        /// 用户Id
        /// </summary>
        public Guid UserId { get; set; }

        /// <summary>
        /// 旧密码
        /// </summary>
        [Required]
        public string OldPassword { get; set; }

        /// <summary>
        /// 新密码
        /// </summary>
        [Required]
        public string NewPassword { get; set; }

        /// <summary>
        /// 确认新密码
        /// </summary>
        [Required]
        public string RequirePassword { get; set; }
    }
}
using System;
using System.ComponentModel.DataAnnotations;

namespace BlogSystem.Model.ViewModels
{
    /// <summary>
    /// 修改用户头像
    /// </summary>
    public class ChangeUserPhotoViewModel
    {
        /// <summary>
        /// 用户Id
        /// </summary>
        public Guid UserId { get; set; }

        /// <summary>
        /// 用户头像
        /// </summary>
        [Required]
        public string ProfilePhoto { get; set; }
    }
}
using System;

namespace BlogSystem.Model.ViewModels
{
    /// <summary>
    /// 修改用户资料
    /// </summary>
    public class ChangeUserInfoViewModel
    {
        /// <summary>
        /// 用户Id
        /// </summary>
        public Guid UserId { get; set; }

        /// <summary>
        /// 账号
        /// </summary>
        public string Account { get; set; }

        /// <summary>
        /// 出生日期
        /// </summary>
        public DateTime BirthOfDate { get; set; }

        /// <summary>
        /// 性别
        /// </summary>
        public Gender Gender { get; set; }
    }
}
using System;

namespace BlogSystem.Model.ViewModels
{
    /// <summary>
    /// 用户详细信息-点击查看主页
    /// </summary>
    public class UserDetailsViewModel
    {
        /// <summary>
        /// 用户Id
        /// </summary>
        public Guid UserId { get; set; }
        /// <summary>
        /// 账号
        /// </summary>
        public string Account { get; set; }
        /// <summary>
        /// 头像
        /// </summary>
        public string ProfilePhoto { get; set; }
        /// <summary>
        /// 年龄
        /// </summary>
        public int Age { get; set; }
        /// <summary>
        /// 性别
        /// </summary>
        public Gender Gender { get; set; }
        /// <summary>
        /// 用户等级
        /// </summary>
        public Level Level { get; set; }
        /// <summary>
        /// 粉丝数
        /// </summary>
        public int FansNum { get; set; }
        /// <summary>
        /// 关注数
        /// </summary>
        public int FocusNum { get; set; }
    }
}

2、用户接口:添加用户方法,如下:

using System;
using BlogSystem.Model;
using BlogSystem.Model.ViewModels;
using System.Threading.Tasks;

namespace BlogSystem.IBLL
{
    /// <summary>
    /// 用户服务接口
    /// </summary>
    public interface IUserService : IBaseService<User>
    {
        /// <summary>
        /// 注册
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        Task Register(RegisterViewModel model);

        /// <summary>
        /// 登录成功返回userId
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        Task<Guid> Login(LoginViewModel model);

        /// <summary>
        /// 修改用户密码
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        Task ChangePassword(ChangePwdViewModel model);

        /// <summary>
        /// 修改用户头像
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        Task ChangeUserPhoto(ChangeUserPhotoViewModel model);

        /// <summary>
        /// 修改用户信息
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        Task ChangeUserInfo(ChangeUserInfoViewModel model);

        /// <summary>
        /// 使用account获取用户信息
        /// </summary>
        /// <param name="account"></param>
        /// <returns></returns>
        Task<UserDetailsViewModel> GetUserInfoByAccount(string account);
    }
}

5、评论接口与ViewModel

1、在Model层的ViewModel文件夹中添加相关的ViewModel

using System;

namespace BlogSystem.Model.ViewModels
{
    public class CommentListViewModel
    {
        /// <summary>
        /// 文章Id
        /// </summary>
        public Guid ArticleId { get; set; }

        /// <summary>
        /// 用户Id
        /// </summary>
        public Guid UserId { get; set; }

        /// <summary>
        /// 账号
        /// </summary>
        public string Account { get; set; }

        /// <summary>
        /// 评论Id
        /// </summary>
        public Guid CommentId { get; set; }

        /// <summary>
        /// 评论内容
        /// </summary>
        public string CommentContent { get; set; }

        /// <summary>
        /// 创建时间
        /// </summary>
        public DateTime CreateTime { get; set; }

    }
}

2、评论接口:添加接口方法,如下:

using BlogSystem.Model;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using BlogSystem.Model.ViewModels;

namespace BlogSystem.IBLL
{
    /// <summary>
    /// 评论服务接口
    /// </summary>
    public interface ICommentService : IBaseService<ArticleComment>
    {
        /// <summary>
        /// 添加评论
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        Task CreateComment(ArticleComment model);

        /// <summary>
        /// 添加回复型评论
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        Task CreateReplyComment(CommentReply model);

        /// <summary>
        /// 通过文章Id获取所有评论
        /// </summary>
        /// <param name="articleId"></param>
        /// <returns></returns>
        Task<List<CommentListViewModel>> GetCommentsByArticleIdAsync(Guid articleId);
    }
}

我们这里暂时只是添加了目前考虑到的一些功能,后续以上的功能可能会进行相关的调整。

四、BLL实现

首先,我们需要对BLL层添加对Model,IDAL,IBLL的引用

1、基类方法

实现基类方法,如下:

using System;
using System.Threading.Tasks;
using BlogSystem.IBLL;
using BlogSystem.IDAL;
using BlogSystem.Model;

namespace BlogSystem.BLL
{
    /// <summary>
    /// 基类方法
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    public class BaseService<TEntity> : IBaseService<TEntity> where TEntity : BaseEntity, new()
    {
        //通过在子类的构造函数中注入,这里是基类,不用构造函数
        public IBaseRepository<TEntity> BaseRepository;

        /// <summary>
        /// 根据Id删除对象
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task RemoveAsync(Guid id)
        {
            await BaseRepository.RemoveAsync(id);
        }

        /// <summary>
        /// 根据实体删除对象
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async Task RemoveAsync(TEntity entity)
        {
            await BaseRepository.RemoveAsync(entity);
        }

        /// <summary>
        /// 查询对象
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<TEntity> GetOneByIdAsync(Guid id)
        {
            return await BaseRepository.GetOneByIdAsync(id);
        }

        /// <summary>
        /// 判断对象是否存在
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<bool> ExistsAsync(Guid id)
        {
            return await BaseRepository.Exists(id);
        }
    }
}

2、文章方法

文章方法实现如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using BlogSystem.IBLL;
using BlogSystem.IDAL;
using BlogSystem.Model;
using BlogSystem.Model.ViewModels;
using Microsoft.EntityFrameworkCore;

namespace BlogSystem.BLL
{
    /// <summary>
    /// 实现文章接口方法
    /// </summary>
    public class ArticleService : BaseService<Article>, IArticleService
    {
        private readonly IArticleRepository _articleRepository;
        private readonly IArticleInCategoryRepository _articleInCategoryRepository;
        private readonly ICategoryRepository _categoryRepository;

        //构造函数注入相关接口
        public ArticleService(IArticleRepository articleRepository, IArticleInCategoryRepository articleInCategoryRepository,
        ICategoryRepository categoryRepository)
        {
            _articleRepository = articleRepository;
            BaseRepository = articleRepository;
            _articleInCategoryRepository = articleInCategoryRepository;
            _categoryRepository = categoryRepository;
        }

        /// <summary>
        /// 创建文章
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task CreateArticleAsync(CreateArticleViewModel model)
        {
            //新增文章
            var article = new Article()
            {
                UserId = model.UserId,
                Title = model.Title,
                Content = model.Content
            };
            await _articleRepository.CreateAsync(article);

            //新增文章所属分类
            var articleId = article.Id;
            foreach (var categoryId in model.CategoryIds)
            {
                await _articleInCategoryRepository.CreateAsync(new ArticleInCategory()
                {
                    ArticleId = articleId,
                    CategoryId = categoryId
                }, false);
            }
            await _articleInCategoryRepository.SavedAsync();
        }

        /// <summary>
        /// 编辑文章
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task EditArticleAsync(EditArticleViewModel model)
        {
            //保存文章更新
            var article = await _articleRepository.GetOneByIdAsync(model.Id);
            article.Title = model.Title;
            article.Content = model.Content;
            await _articleRepository.EditAsync(article);

            //删除所属分类
            var categoryIds = _articleInCategoryRepository.GetAll();
            foreach (var categoryId in categoryIds)
            {
                await _articleInCategoryRepository.RemoveAsync(categoryId, false);
            }
            //添加所属分类
            foreach (var categoryId in model.CategoryIds)
            {
                await _articleInCategoryRepository.CreateAsync(new ArticleInCategory()
                {
                    ArticleId = model.Id,
                    CategoryId = categoryId
                }, false);
            }
            //统一保存
            await _articleInCategoryRepository.SavedAsync();
        }

        /// <summary>
        /// 获取文章详情
        /// </summary>
        /// <param name="articleId"></param>
        /// <returns></returns>
        public async Task<ArticleDetailsViewModel> GetArticleDetailsByArticleIdAsync(Guid articleId)
        {
            var data = await _articleRepository.GetAll().Include(m => m.User).Where(m => m.Id == articleId)
                .Select(m => new ArticleDetailsViewModel
                {
                    Id = m.Id,
                    Title = m.Title,
                    Content = m.Content,
                    CreateTime = m.CreateTime,
                    Account = m.User.Account,
                    ProfilePhoto = m.User.ProfilePhoto,
                    GoodCount = m.GoodCount,
                    BadCount = m.BadCount
                }).FirstAsync();
            //处理分类
            var categories = await _articleInCategoryRepository.GetAll().Include(m => m.Category)
                .Where(m => m.ArticleId == data.Id).ToListAsync();
            data.CategoryIds = categories.Select(m => m.CategoryId).ToList();
            data.CategoryNames = categories.Select(m => m.Category.CategoryName).ToList();
            return data;
        }

        /// <summary>
        /// 根据用户Id获取文章列表信息
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public async Task<List<ArticleListViewModel>> GetArticlesByUserIdAsync(Guid userId)
        {
            var list = await _articleRepository.GetAllByOrder(false).Include(m => m.User).Where(m => m.UserId == userId)
                .Select(m => new ArticleListViewModel()
                {
                    ArticleId = m.Id,
                    Title = m.Title,
                    Content = m.Content,
                    CreateTime = m.CreateTime,
                    Account = m.User.Account,
                    ProfilePhoto = m.User.ProfilePhoto
                }).ToListAsync();
            return list;
        }

        /// <summary>
        /// 通过分类Id获取文章列表
        /// </summary>
        /// <param name="categoryId"></param>
        /// <returns></returns>
        public async Task<List<ArticleListViewModel>> GetArticlesByCategoryIdAsync(Guid categoryId)
        {
            var data = await _categoryRepository.GetOneByIdAsync(categoryId);
            var userId = data.UserId;
            return await GetArticlesByUserIdAsync(userId);
        }

        /// <summary>
        /// 获取用户文章数量
        /// </summary>
        /// <param name="userid"></param>
        /// <returns></returns>
        public async Task<int> GetArticleCountByUserIdAsync(Guid userid)
        {
            return await _articleRepository.GetAll().CountAsync(m => m.UserId == userid);
        }

        /// <summary>
        /// 看好数量+1
        /// </summary>
        /// <param name="articleId"></param>
        /// <returns></returns>
        public async Task AddGoodCount(Guid articleId)
        {
            var article = await _articleRepository.GetOneByIdAsync(articleId);
            article.GoodCount++;
            await _articleRepository.EditAsync(article);
        }

        /// <summary>
        /// 不看好数量+1
        /// </summary>
        /// <param name="articleId"></param>
        /// <returns></returns>
        public async Task AddBadCount(Guid articleId)
        {
            var article = await _articleRepository.GetOneByIdAsync(articleId);
            article.BadCount--;
            await _articleRepository.EditAsync(article);
        }
    }
}

3、分类方法

实现分类方法,如下:

using BlogSystem.IBLL;
using BlogSystem.IDAL;
using BlogSystem.Model;
using BlogSystem.Model.ViewModels;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace BlogSystem.BLL
{
    public class CategoryService : BaseService<Category>, ICategoryService
    {
        private readonly ICategoryRepository _categoryRepository;

        public CategoryService(ICategoryRepository categoryRepository)
        {
            _categoryRepository = categoryRepository;
            BaseRepository = categoryRepository;
        }

        /// <summary>
        /// 创建分类
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task CreateCategory(CreateOrEditCategoryViewModel model)
        {
            await _categoryRepository.CreateAsync(new Category()
            {
                UserId = model.UserId,
                CategoryName = model.CategoryName
            });
        }

        /// <summary>
        /// 编辑分类
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task EditCategory(CreateOrEditCategoryViewModel model)
        {
            await _categoryRepository.EditAsync(new Category()
            {
                UserId = model.UserId,
                CategoryName = model.CategoryName
            });
        }

        /// <summary>
        ///  通过用户Id获取所有分类
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public Task<List<CategoryListViewModel>> GetCategoryByUserIdAsync(Guid userId)
        {
            return _categoryRepository.GetAll().Where(m => m.UserId == userId).Select(m => new CategoryListViewModel
            {
                CategoryName = m.CategoryName
            }).ToListAsync();
        }
    }
}

4、用户方法

实现用户方法,如下:

using BlogSystem.IBLL;
using BlogSystem.IDAL;
using BlogSystem.Model;
using BlogSystem.Model.ViewModels;
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using System.Threading.Tasks;

namespace BlogSystem.BLL
{
    public class UserService : BaseService<User>, IUserService
    {
        private readonly IUserRepository _userRepository;

        public UserService(IUserRepository userRepository)
        {
            _userRepository = userRepository;
            BaseRepository = userRepository;
        }

        /// <summary>
        /// 用户注册
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task Register(RegisterViewModel model)
        {
           //判断账户是否存在
            if (!await _userRepository.GetAll().AnyAsync(m => m.Account == model.Account))
            {
                await _userRepository.CreateAsync(new User()
                {
                    Account = model.Account,
                    Password = model.Password
                });
            }
        }

        /// <summary>
        /// 用户登录
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<Guid> Login(LoginViewModel model)
        {
            var user = await _userRepository.GetAll().FirstOrDefaultAsync(m => m.Account == model.Account && m.Password == model.Password);
            return user != null ? user.Id : new Guid();
        }

        /// <summary>
        /// 修改用户密码
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task ChangePassword(ChangePwdViewModel model)
        {
            if (await _userRepository.GetAll().AnyAsync(m => m.Id == model.UserId && m.Password == model.OldPassword))
            {
                var user = await _userRepository.GetAll().FirstOrDefaultAsync(m => m.Id == model.UserId && m.Password == model.OldPassword);
                user.Password = model.NewPassword;
                await _userRepository.EditAsync(user);
            }
        }

        /// <summary>
        /// 修改用户照片
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task ChangeUserPhoto(ChangeUserPhotoViewModel model)
        {
            var user = await _userRepository.GetAll().FirstAsync(m => m.Id == model.UserId);
            user.ProfilePhoto = model.ProfilePhoto;
            await _userRepository.EditAsync(user);
        }

        /// <summary>
        /// 修改用户信息
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task ChangeUserInfo(ChangeUserInfoViewModel model)
        {
            var user = await _userRepository.GetAll().FirstAsync(m => m.Id == model.UserId);
            user.Account = model.Account;
            user.Gender = model.Gender;
            user.BirthOfDate = model.BirthOfDate;
            await _userRepository.EditAsync(user);
        }

        /// <summary>
        /// 通过账号名称获取用户信息
        /// </summary>
        /// <param name="account"></param>
        /// <returns></returns>
        public async Task<UserDetailsViewModel> GetUserInfoByAccount(string account)
        {
            if (await _userRepository.GetAll().AnyAsync(m => m.Account == account))
            {
                return await _userRepository.GetAll().Where(m => m.Account == account).Select(m =>
                    new UserDetailsViewModel()
                    {
                        UserId = m.Id,
                        Account = m.Account,
                        ProfilePhoto = m.ProfilePhoto,
                        Age = DateTime.Now.Year - m.BirthOfDate.Year,
                        Gender = m.Gender,
                        Level = m.Level,
                        FansNum = m.FansNum,
                        FocusNum = m.FocusNum
                    }).FirstAsync();
            }
            return new UserDetailsViewModel();
        }
    }
}

5、评论方法

实现评论方法,如下:

using BlogSystem.IBLL;
using BlogSystem.IDAL;
using BlogSystem.Model;
using BlogSystem.Model.ViewModels;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace BlogSystem.BLL
{
    public class CommentService : BaseService<ArticleComment>, ICommentService
    {
        private readonly IArticleCommentRepository _commentRepository;
        private readonly ICommentReplyRepository _commentReplyRepository;

        public CommentService(IArticleCommentRepository commentRepository, ICommentReplyRepository commentReplyRepository)
        {
            _commentRepository = commentRepository;
            BaseRepository = commentRepository;
            _commentReplyRepository = commentReplyRepository;
        }

        /// <summary>
        /// 添加评论
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task CreateComment(ArticleComment model)
        {
            await _commentRepository.CreateAsync(model);
        }

        /// <summary>
        /// 添加回复型评论
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task CreateReplyComment(CommentReply model)
        {
            await _commentReplyRepository.CreateAsync(model);
        }

        /// <summary>
        /// 根据文章Id获取评论信息
        /// </summary>
        /// <param name="articleId"></param>
        /// <returns></returns>
        public async Task<List<CommentListViewModel>> GetCommentsByArticleIdAsync(Guid articleId)
        {
            return await _commentReplyRepository.GetAllByOrder(false).Where(m => m.ArticleId == articleId)
                .Include(m => m.ArticleComment).Include(m => m.User).Select(m => new CommentListViewModel()
                {
                    ArticleId = m.ArticleId,
                    UserId = m.UserId,
                    Account = m.User.Account,
                    CommentId = m.Id,
                    CommentContent = m.Content,
                    CreateTime = m.CreateTime
                })
                .ToListAsync();
        }
    }
}

本章只是从整体上将DAL层和BLL的进行了初步的完善,后续会进一步调整,完~

本人知识点有限,若文中有错误的地方请及时指正,方便大家更好的学习和交流。

本文的代码结构和方法参考了B站一位UP主的视频内容,地址如下:任生风影

原创文章声明
原文地址:https://www.cnblogs.com/Jscroop/p/12846644.html