.net core创建webapi之------构建项目
先完成之前的数据库连接。。。然后实现数据库数据的增删改差功能
1,创建Models文件夹,里面存放数据库操作实体和供外界调用的实体类
这里说一下为什么写两套实体,一是为了数据库安全不暴露数据库。
二是为了数据分开,这样接口升级之后仍能保证原接口访问正常。
2,创建数据库操作服务Services文件夹,一般来讲对一块业务功能的数据库操作放在这里。
实例如下:在Services文件夹下创建接口IUserRepository.cs
代码如下:
using RoutineApi.Models.Entities; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace RoutineApi.Services { public interface IUserRepository { /// <summary> /// 通过账号返回用户实体 /// </summary> /// <param name="code"></param> /// <returns></returns> Task<ZGXT_USER> GetUserByCode(string code); /// <summary> /// 返回所有的用户列表 /// </summary> /// <returns></returns> Task<IEnumerable<ZGXT_USER>> GetAllUser(); /// <summary> /// 添加用户 /// </summary> /// <param name="user"></param> bool AddUser(ZGXT_USER user); /// <summary> /// 修改用户数据 /// </summary> /// <param name="user"></param> bool UpdateUser(ZGXT_USER user); /// <summary> /// 根据userID删除用户 /// </summary> /// <param name="userID"></param> /// <returns></returns> bool DeleteUser(long userID); } }
然后写这个接口的实现类UserRepository.cs代码如下:
using RoutineApi.DBUtility; using RoutineApi.Models.DtoModels; using RoutineApi.Models.Entities; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Utility; namespace RoutineApi.Services { public class UserRepository : IUserRepository { private readonly DbHelper _dbHelper; public UserRepository(DbHelper dbHelper) { _dbHelper = dbHelper ?? throw new ArgumentNullException(nameof(dbHelper)); ; } public bool AddUser(ZGXT_USER user) { try { if (user == null) { throw new ArgumentNullException(nameof(user)); } return _dbHelper.Insert(user); } catch(Exception ex) { LogMgr.Error(ex); throw new Utility.Web.RequestException(ex.Message); } } public bool DeleteUser(long userID) { try { //根据userID获取用户 var user = _dbHelper.First<ZGXT_USER>(x => x.ID == userID); return _dbHelper.Delete(user, "ID"); } catch(Exception ex) { LogMgr.Error(ex); throw new Utility.Web.RequestException(ex.Message); } } public async Task<IEnumerable<ZGXT_USER>> GetAllUser() { try { var users = _dbHelper.Query<ZGXT_USER>(); return await Task.Run(function: () => users.AsEnumerable()); } catch (Exception ex) { LogMgr.Error(ex); throw new Utility.Web.RequestException(ex.Message); } } public async Task<ZGXT_USER> GetUserByCode(string code) { try { if (code == string.Empty) { throw new ArgumentNullException("code为空"); } var user = _dbHelper.First<ZGXT_USER>(x => x.CODE == code); return await Task.Run(function: () => user); } catch (Exception ex) { LogMgr.Error(ex); throw new Utility.Web.RequestException(ex.Message); } } public bool UpdateUser(ZGXT_USER user) { try { if (user == null) { throw new ArgumentNullException(nameof(user)); } return _dbHelper.Update(user, "ID"); } catch(Exception ex) { LogMgr.Error(ex); throw new Utility.Web.RequestException(ex.Message); } } } }
这里需要注意,.net core里面的操作一般都是使用依赖注入操作(IOC),这里通过构造函数的方式进行依赖注入数据库操作类DbHelper
3,数据库操作service完成之后要在Startup.cs类的ConfigureServices里面注册service方可使用。代码注册方式有三种,跟服务的生存周期有关
services.AddTransient<IOperationTransient, Operation>();//暂时生存期服务 (AddTransient) 是每次从服务容器进行请求时创建的。 这种生存期适合轻量级、 无状态的服务
services.AddScoped<IOperationScoped, Operation>();//作用域生存期服务 (AddScoped) 以每个客户端请求(连接)一次的方式创建。
在中间件内使用有作用域的服务时,请将该服务注入至 Invoke
或 InvokeAsync
方法。 请不要通过构造函数注入进行注入,因为它会强制服务的行为与单一实例类似
services.AddSingleton<IOperationSingleton, Operation>();//单一实例生存期服务 (AddSingleton) 是在第一次请求时(或者在运行 Startup.ConfigureServices
并且使用服务注册指定实例时)创建的。
每个后续请求都使用相同的实例。 如果应用需要单一实例行为,建议允许服务容器管理服务的生存期。 不要实现单一实例设计模式并提供用户代码来管理对象在类中的生存期。
这里详细的服务生存周期问题可以参考:https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-3.1#service-lifetimes
注册代码如下:
services.AddSingleton<DbHelper>(); services.AddSingleton<IUserRepository, UserRepository>(); services.AddSingleton<IPowerRepository, PowerRepository>(); services.AddSingleton<IPatientRepository, PatientRepository>(); services.AddSingleton<IFormRepository, FormRepository>();
注意除了一般服务类需要注册,数据库操作类也需要注册到容器内才可使用。
4,编写业务逻辑处理controller,在Controllers文件夹下创建UserController.cs类。
代码如下:
public class UserController : ControllerBase { private readonly IUserRepository _userRepository; private readonly IPowerRepository _powerRepository; public UserController(IUserRepository userRepository, IPowerRepository powerRepository) { _userRepository = userRepository; _powerRepository = powerRepository; } /// <summary> /// 获取所有用户 /// </summary> /// <returns></returns> [HttpGet] public async Task<ActionResult<IEnumerable<UserDto>>> GetAllUser() { var users = await _userRepository.GetAllUser(); //users = users.Where(x => x.DATASTATE == "0"); if (!users.Any()) { return NoContent(); } //根据User转化为UserDto var dtoUsers = new List<UserDto>(); foreach (var user in users) { dtoUsers.Add(UserToDto(user)); } //var userDtos = _mapper.Map<IEnumerable<UserDto>>(users); return Ok(dtoUsers); } /// <summary> /// 判断用户名密码是否正确,如果正确返回用户实体,不正确则返回错误信息 /// </summary> /// <param name="code"></param> /// <param name="password"></param> /// <returns></returns> [HttpGet(template: "{code}&&{password}", Name = "CheckLogin")] public async Task<ActionResult<UserDto>> CheckLogin(string code, string password) { if (code == string.Empty || password == string.Empty) { return NoContent(); } //string md5Pwd = Security.MD5(password); var user = await _userRepository.GetUserByCode(code); Message message = new Message(); if (user == null) { message.MessageContent = "该账户不存在"; message.Code = Code.该账号不存在; return Ok(message); } if (user.PASSWORD == password) { if (user.DATASTATE == "9") { message.MessageContent = "该账户已停用"; message.Code = Code.该账户已停用; return Ok(message); } else { UserDto userDtoReturn = UserToDto(user); return Ok(userDtoReturn); } } else { message.MessageContent = "密码错误"; message.Code = Code.密码错误; return Ok(message); } } }
第一步需要在Controller上面写
[ApiController]
[Route("api/[controller]")]
这样才能通过路由访问接口,api/[controller]这个来确定接口的基本路径。
第二步通过构造函数注入数据操作服务的service。
第三步写实际的业务方法。
在方法上分为四大类增([HttpPost()])删([HttpDelete])改(HttpPut())查([HttpGet()]),需要在方法上注明,Get可以省post不可以。
接口的参数这里是json数据,获取分为直接传参直接定义参数类型即可,传json数据需要用【FromBody】,【FromHeader】来接收client的传参。代码如下:
/// <summary> /// 新增用户 /// </summary> /// <param name="userDto"></param> /// <returns></returns> [HttpPost] public IActionResult Add([FromBody]UserDto userDto) { if (userDto != null) { var user = ToUser(userDto); //密码不加密之后再存入系统 //user.PASSWORD = Security.MD5(user.PASSWORD); var added = _userRepository.AddUser(user); Message message = new Message(); if (added) { message.MessageContent = "操作成功"; message.Code = Code.操作成功; } else { message.MessageContent = "操作失败"; message.Code = Code.操作失败; } return Ok(message); } else { return NoContent(); } }
方法的返回类型基本是IActionResult,可以直接写实现类ActionResult确定返回类型,如:
[HttpGet(template: "/{RecordNo}", Name = "GetPatientByRecordNo")] public async Task<ActionResult<IEnumerable<PatientDto>>> GetPatientByRecordNo(string RecordNo) { if (RecordNo == string.Empty) { return NoContent(); } else { var patients = await _patientRepository.GetPatientByRecordNo(RecordNo); Message message = new Message(); if (patients.Count()==0) { message.Code = Code.该病历号不存在住院信息; message.MessageContent = "该病历号不存在住院信息"; return Ok(message); } else { List<PatientDto> patientList = new List<PatientDto>(); foreach(var patient in patients) { var patientDto = ReverseDto.PatientToDto(patient); patientList.Add(patientDto); } return Ok(patientList); } } }
至此,这个.net core创建的项目工程功能已处理完毕,下一篇是这个项目的部署发布,接口文档的配置,跨域访问问题的解决。