上一篇我們使用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主的視頻內容,地址如下:任生風影