【asp.net core 系列】- 11 Service层的实现样板
0.前言
在《asp.net core 系列》之实战系列中,我们在之前的篇幅中对项目有了一个大概的认知,也搭建了一个基础的项目骨架。那么就让我们继续完善这个骨架,让它更加丰满。这一篇,我将带领小伙伴们一起实现用户管理功能。
1. 数据表
一般情况下,我们会把用户表和登录信息表放在两个表里。为什么会这样设计呢?出于以下几种考虑:
- 使功能分割,用户信息管理是用户管理,登录是登录
- 增加安全,降低无关信息的查询,例如访问登录接口不会连带检索用户的普通信息,当进行用户信息管理的时候,不会把登录信息也带过来
等等
废话不多说,直接上代码:
namespace Data.Enums
{
/// <summary>
/// 登录类型
/// </summary>
public enum LoginType : byte
{
/// token登录
Token,
/// 用户名密码
Password
}
/// <summary>
/// 性别
/// </summary>
public enum SexEnum
{
/// 男
Male,
/// 女
Female,
/// 隐私
None
}
}
SysUserAuthEntity.cs
using Data.Enums;
using Data.Infrastructure;
namespace Data.Models
{
public class SysUserAuthEntity : BaseEntity<int>
{
public string UserName { get; set; }
public string Password { get; set; }
public LoginType LoginType { get; set;}
}
}
SysUserInfoEntity.cs
using System;
using Data.Enums;
using Data.Infrastructure;
namespace Data.Models
{
public class SysUserInfoEntity : BaseEntity<int>
{
public string NickName { get; set; }
public string ImageUrl { get; set; }
public SexEnum Sex { get; set; }
public DateTime? BirthDay { get; set; }
public int SysUserAuthId { get; set; }
public virtual SysUserAuthEntity SysUserAuth { get; set; }
}
}
这里并没有使用数据库Sql语句作为数据库描述,而是使用了Entity类作为描述,这是因为数据库到实体类之间还是有一层转换,对于开发而言接触更多的是实体类,而不是数据表。
2. 生成 Repository相关
使用工具代码的方式有很多,我在这里推荐一种, Test项目中,添加一个测试类,具体代码如下:
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Text;
using Utils.Develop;
namespace Test
{
public class DevelopTest
{
[Test]
public void TetDevelop()
{
var d = Develop.CurrentDirect;
Console.WriteLine(d);
Assert.IsTrue(d.Contains("template"));
var entities = Develop.LoadEntities();
foreach (var item in entities)
{
Console.WriteLine(item.FullName);
}
}
[Test]
public void TestCreateDevelop()
{
var entities = Develop.LoadEntities();
foreach (var item in entities)
{
Develop.CreateRepositoryInterface(item);
Develop.CreateRepositoryImplement(item);
Develop.CreateEntityTypeConfig(item);
}
Assert.Pass();
}
}
}
具体的命令行执行比较麻烦,会执行所有的测试单元:
cd Test/
dotnet test
当然了,IDE支持单个测试单元的执行,具体操作这里就不做过多的介绍了。
3. Service 接口和实现类
通常Service接口会提供一个简单Crud的Service接口,然后其他业务接口继承该接口。这样可以减少代码的重复,因为重复的代码在开发过程中是非常讨厌的一种情况,因为一旦一处发生变更,其他的也有可能发生变更。所以遇到重复代码一般都会进行一定程度的封装:
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using Data.Infrastructure;
namespace Service.Insfrastructure
{
public interface BaseService<T>
{
T Get(object key);
T Get(Expression<Func<T, bool>> predicate);
PageModel<T> SearchPage(PageCondition<T> condition);
void Delete(Expression<Func<T, bool>> predicate);
void Update(T entity);
List<T> Search(Expression<Func<T, bool>> predicate);
}
}
暂时就提供了这些最常见的请求方法。
在Service.Implements项目中:
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using Data.Infrastructure;
using Domain.Insfrastructure;
using Service.Insfrastructure;
namespace Service.Implements.Insfrastructure
{
public abstract class BaseServiceImpl<T> : BaseService<T>
{
private IRepository<T> LocalRepository { get; }
protected BaseServiceImpl(IRepository<T> repository)
{
LocalRepository = repository;
}
public T Get(object key)
{
return LocalRepository.Get(key);
}
public T Get(Expression<Func<T, bool>> predicate)
{
return LocalRepository.Get(predicate);
}
public PageModel<T> SearchPage(PageCondition<T> condition)
{
return LocalRepository.Search(condition);
}
public void Delete(Expression<Func<T, bool>> predicate)
{
LocalRepository.Delete(predicate);
}
public void Update(T entity)
{
LocalRepository.Update(entity);
}
public List<T> Search(Expression<Func<T, bool>> predicate)
{
return LocalRepository.Search(predicate);
}
}
}
这个类设置为抽象类。
4. 用户管理的接口
先创建了两个简单的示范接口:
using Data.Models;
using Service.Insfrastructure;
namespace Service
{
public interface ISysUserService : BaseService<SysUserInfoEntity>
{
void Register(SysUserAuthEntity auth, SysUserInfoEntity info);
void ChangePassword(int userId, string oldPwd, string newPwd);
}
}
实现类:
using System;
using Data.Models;
using Domain.Repository;
using Service.Implements.Insfrastructure;
namespace Service.Implements
{
public class SysUserServiceImpl : BaseServiceImpl<SysUserInfoEntity>, ISysUserService
{
protected ISysUserAuthRepository AuthRepository { get; }
protected ISysUserInfoRepository InfoRepository { get; }
public SysUserServiceImpl(ISysUserAuthRepository authRepository, ISysUserInfoRepository infoRepository) : base(
infoRepository)
{
AuthRepository = authRepository;
InfoRepository = infoRepository;
}
public void Register(SysUserAuthEntity auth, SysUserInfoEntity info)
{
var authItem = AuthRepository.Get(p => p.LoginType == auth.LoginType && p.UserName == auth.UserName);
if (authItem != null)
{
throw new Exception("用户信息已经存在");
}
info.SysUserAuth = auth;
InfoRepository.Insert(info);
}
public void ChangePassword(int userId, string oldPwd, string newPwd)
{
var info = InfoRepository.Get(userId);
var auth = AuthRepository.Get(info.SysUserAuthId);
if (oldPwd == null || oldPwd != auth?.Password)
{
throw new Exception("原密码错误");
}
auth.Password = newPwd;
}
}
}
这里没对密码进行加密处理,直接使用明文。这在正式开发中是不允许的,密码不能使用明文保存。当然,这也不是最终代码,下一篇我们将介绍一下.net core中常见的加密实现。
5. 总结
这一篇通过几个简单的示例为大家介绍了一下Service层的开发逻辑以及理念。下一篇将为大家介绍一下.net core中几种简单的加密实现。
更多内容烦请关注我的博客《高先生小屋》
【asp.net core 系列】- 11 Service层的实现样板的更多相关文章
- asp.net core 系列 11 配置configuration (下)
四. 文件配置提供程序AddIniFile. AddXmlFile.AddJsonFile FileConfigurationProvider 是从文件系统加载配置的基类. 以下配置提供程序专用于特定 ...
- 【目录】asp.net core系列篇
随笔分类 - asp.net core系列篇 asp.net core系列 68 Filter管道过滤器 摘要: 一.概述 本篇详细了解一下asp.net core filters,filter叫&q ...
- 技术的正宗与野路子 c#, AOP动态代理实现动态权限控制(一) 探索基于.NET下实现一句话木马之asmx篇 asp.net core 系列 9 环境(Development、Staging 、Production)
黄衫女子的武功似乎与周芷若乃是一路,飘忽灵动,变幻无方,但举手抬足之间却是正而不邪,如说周芷若形似鬼魅,那黄衫女子便是态拟神仙. 这段描写出自<倚天屠龙记>第三十八回. “九阴神抓”本是& ...
- Asp.net Core 系列之--3.领域、仓储、服务简单实现
ChuanGoing 2019-11-11 距离上篇近两个月时间,一方面时因为其他事情耽搁,另一方面也是之前准备不足,关于领域驱动有几个地方没有想通透,也就没有继续码字.目前网络包括园子里大多领域驱 ...
- Ajax跨域问题及解决方案 asp.net core 系列之允许跨越访问(Enable Cross-Origin Requests:CORS) c#中的Cache缓存技术 C#中的Cookie C#串口扫描枪的简单实现 c#Socket服务器与客户端的开发(2)
Ajax跨域问题及解决方案 目录 复现Ajax跨域问题 Ajax跨域介绍 Ajax跨域解决方案 一. 在服务端添加响应头Access-Control-Allow-Origin 二. 使用JSONP ...
- 【asp.net core 系列】6 实战之 一个项目的完整结构
0. 前言 在<asp.net core 系列>之前的几篇文章中,我们简单了解了路由.控制器以及视图的关系以及静态资源的引入,让我们对于asp.net core mvc项目有了基本的认识. ...
- asp.net core系列 40 Web 应用MVC 介绍与详细示例
一. MVC介绍 MVC架构模式有助于实现关注点分离.视图和控制器均依赖于模型. 但是,模型既不依赖于视图,也不依赖于控制器. 这是分离的一个关键优势. 这种分离允许模型独立于可视化展示进行构建和测试 ...
- asp.net core系列 39 Web 应用Razor 介绍与详细示例
一. Razor介绍 在使用ASP.NET Core Web开发时, ASP.NET Core MVC 提供了一个新特性Razor. 这样开发Web包括了MVC框架和Razor框架.对于Razor来说 ...
- asp.net core 系列 17 通用主机 IHostBuilder
一.概述 ASP.NET Core 通用主机 (HostBuilder),该主机对于托管不处理 HTTP 请求的应用非常有用.通用主机的目标是将 HTTP 管道从 Web 主机 API 中分离出来,从 ...
随机推荐
- 【java】关键字volatile
volatile 1. 含义: volatile是JVM提供的轻量级的同步机制,具有三个特点:保证可见性.不保证原子性.禁止指令重排. 1.1 保证可见性 一个线程修改了共享变量并写回主内存,其他线程 ...
- [ES6系列-03]ES6中关于参数相关特性详解(参数默认值与参数解构赋值与剩余参数)
[原创] 码路工人 大家好,这里是码路工人有力量,我是码路工人,你们是力量. 今天总结一下 ES6 中跟参数相关的内容. 欢迎补充斧正.留言交流. 让我们互相学习一起进步. 1. ES6 参数默认值( ...
- eatwhatApp开发实战(十三)
这次内容,我们就项目中添加商店名称的EditText进行修改,让添加按钮随着edittext的内容而改变. 上代码,首先是xml文件上对两个控件的修改: <RelativeLayout andr ...
- [JavaWeb基础] 021.Action中result的各种转发类型
在struts2中, struts.xml中result的类型有多种,它们类似于struts1中的forward,常用的类型有dispatcher(默认值).redirect.redirectActi ...
- unix 密码破解,zip破解总结
unix /etc/passwd 破解,假设的前两位是salt import crypt #数据比较 def password_crak(pass_word): salt = pass_word[0: ...
- 一文彻底搞懂BERT
一.什么是BERT? 没错下图中的小黄人就是文本的主角Bert ,而红色的小红人你应该也听过,他就是ELMo.2018年发布的BERT 是一个 NLP 任务的里程碑式模型,它的发布势必会带来一个 NL ...
- itext7史上最全实战总结
1. itext7史上最全实战总结 1.1. 前言 最近有个需求需要我用Java手动写一份PDF报告,经过考察几种pdf开源代码,最终选取了itext7,此版本为7.1.11,由于发现网上关于该工具的 ...
- Rocket - 断句 - Diplomatic Design Patterns: A TileLink Case Study
https://mp.weixin.qq.com/s/afRVgTCYs1Mxu898uSmVaQ 整理一篇介绍Diplomacy和TileLink的文章. 原文链接: https://carrv ...
- Physic Design:Floorplan算法概览
仅用于学习交流,转载请联系本人. 1 floorplan是什么 floorplan常被翻译成布图规划,是指在芯片级别上对模块进行布局,也就是哪个单元放在什么地方,但是单元内部的具体布局并不关心.该步骤 ...
- Java实现 LeetCode 127 单词接龙
127. 单词接龙 给定两个单词(beginWord 和 endWord)和一个字典,找到从 beginWord 到 endWord 的最短转换序列的长度.转换需遵循如下规则: 每次转换只能改变一个字 ...