DncZeus实战开源项目(五)CRUD操作演示
CRUD接口实例---NvrServer
- 新建实体类
// NvrServer.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using static DncZeus.Api.Entities.Enums.CommonEnum;
namespace DncZeus.Api.Entities
{
public class NvrServer
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
[StringLength(50)]
public string Name { get; set; }
[Required]
[StringLength(50)]
public string IP { get; set; }
[StringLength(100)]
public string Notice { get; set; }
public IsDeleted IsDeleted { get; set; }
public DateTime CreateTime { get; set; }
public DateTime? UpdateTime { get; set; }
// 数据库导航属性:使用 virtual 以支持延迟加载
public virtual ICollection<Camera> Cameras { get; set; }
}
}
- 在
dbContext中注册并映射到数据库
// DncAuthDbContext.cs
using Microsoft.EntityFrameworkCore;
namespace DncZeus.Api.Entities
{
public class DncZeusDbContext : DbContext
{
......
public DbSet<NvrServer> NvrServer { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
......
modelBuilder.Entity<NvrServer>(entity =>
{
entity.HasKey(e => e.Id);
entity.Property(e => e.Name).IsRequired();
entity.Property(e => e.IP).IsRequired();
});
......
base.OnModelCreating(modelBuilder);
}
}
}
- 新建
视图模型ViewModel- 本质就是
模型的序列化- 定义字段的校验规则,序列化字段并返回给前端
- 意义: 当前端传过来的字段不符合要求时,会报错对应的异常
- 本质就是
// ViewModels.Equitments.NvrServer.NvrServerCreateViewModel.cs
using System.ComponentModel.DataAnnotations;
namespace DncZeus.Api.ViewModels.Equitments.NvrServer
{
public class NvrServerCreateViewModel
{
[Required(ErrorMessage = "请输入服务器名称")]
[StringLength(50, ErrorMessage = "服务器名称长度不能超过50个字符")]
public string Name { get; set; }
[Required(ErrorMessage = "请输入IP地址")]
[StringLength(50, ErrorMessage = "IP地址长度不能超过50个字符")]
public string IP { get; set; }
[StringLength(100, ErrorMessage = "备注长度不能超过100个字符")]
public string Notice { get; set; }
}
}
// NvrServerEditViewModel.cs
using System.ComponentModel.DataAnnotations;
namespace DncZeus.Api.ViewModels.Equitments.NvrServer
{
public class NvrServerEditViewModel
{
public int Id { get; set; }
[Required(ErrorMessage = "请输入服务器名称")]
[StringLength(50, ErrorMessage = "服务器名称长度不能超过50个字符")]
public string Name { get; set; }
[Required(ErrorMessage = "请输入IP地址")]
[StringLength(50, ErrorMessage = "IP地址长度不能超过50个字符")]
public string IP { get; set; }
[StringLength(100, ErrorMessage = "备注长度不能超过100个字符")]
public string Notice { get; set; }
public bool IsDeleted { get; set; }
}
}
// NvrServerJsonModel.cs
namespace DncZeus.Api.ViewModels.Equitments.NvrServer
{
public class NvrServerJsonModel
{
public int Id { get; set; }
public string Name { get; set; }
public string IP { get; set; }
public string Notice { get; set; }
public bool IsDeleted { get; set; }
public string CreateTime { get; set; }
public string UpdateTime { get; set; }
public int CameraCount { get; set; }
}
}
- 新建
请求模型- 本质就是
分页,排序和关键字搜索- 基类
RequestPayload已自带分页和排序
- 基类
- 本质就是
// RequestPayload.Equitments.NvrServer.cs
using DncZeus.Api.RequestPayload;
namespace DncZeus.Api.RequestPayload.Equitments.NvrServer
{
public class NvrServerRequestPayload:RequestPayload
{
public string Kw { get; set; }
}
}
-
AutoMapper配置映射-
作用
- 在不同类型之间自动转换,避免手动赋值
// 没有 AutoMapper 时 var jsonModel = new UserJsonModel { Id = user.Id, Name = user.Name, // ... 需要手动赋值每个属性 }; // 使用 AutoMapper var jsonModel = _mapper.Map<DncUser, UserJsonModel>(user); // 自动转换- 配置映射规则: 定义
实体和ViewModel之间的关系
// 基本映射 CreateMap<DncUser, UserJsonModel>(); // 复杂映射(自定义字段映射) CreateMap<DncPermission, PermissionJsonModel>() .ForMember(d => d.MenuName, s => s.MapFrom(x => x.Menu.Name)) // 关联表字段 .ForMember(d => d.PermissionTypeText, s => s.MapFrom(x => x.Type.ToString())); // 类型转文本- 支持
实体↔ViewModel的双向转换:
// 实体 → ViewModel CreateMap<DncUser, UserEditViewModel>(); // ViewModel → 实体 CreateMap<UserEditViewModel, DncUser>();- 实际应用
// 查询列表 var data = list.Select(_mapper.Map<DncUser, UserJsonModel>); // 创建时映射 var entity = _mapper.Map<UserCreateViewModel, DncUser>(model); // 编辑时映射 entity.DisplayName = model.DisplayName; // 手动赋值 // 或者 entity = _mapper.Map<UserEditViewModel, DncUser>(model); // 自动映射
-
-
CRUD接口
// V1.Equitments.NvrServer.cs
using AutoMapper;
using DncZeus.Api.Entities;
using DncZeus.Api.Entities.Enums;
using DncZeus.Api.Extensions;
using DncZeus.Api.Extensions.AuthContext;
using DncZeus.Api.Extensions.DataAccess;
using DncZeus.Api.Models.Response;
using DncZeus.Api.RequestPayload.Equitments.NvrServer;
using DncZeus.Api.ViewModels.Equitments.NvrServer;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using static DncZeus.Api.Entities.Enums.CommonEnum;
namespace DncZeus.Api.Controllers.Api.V1.Equitments.NvrServer
{
[Route("api/v1/nvrserver/[action]")]
[ApiController]
public class NvrServerController : ControllerBase
{
private readonly DncZeusDbContext _dbContext;
private readonly IMapper _mapper;
// 注入dbContext和mapper
public NvrServerController(DncZeusDbContext dbContext, IMapper mapper)
{
_dbContext = dbContext;
_mapper = mapper;
}
[HttpPost]
public IActionResult List(NvrServerRequestPayload payload)
/* payload是个对象
{
"pageSize": 6,
"currentPage": 1,
"sort": [
{
"field": "Name",
"direct": "DESC"
}
],
"kw": "服务器"
}
*/
{
using (_dbContext)
{
// 获取数据库所有的记录集
var query = _dbContext.Set<Entities.NvrServer>().AsQueryable();
// 筛选未删除的记录
query = query.Where(x => x.IsDeleted == IsDeleted.No);
// 当Kw不为空值时,搜索查询
if (!string.IsNullOrEmpty(payload.Kw))
{
query = query.Where(x => x.Name.Contains(payload.Kw.Trim()) ||
x.IP.Contains(payload.Kw.Trim()) ||
(x.Notice != null && x.Notice.Contains(payload.Kw.Trim())));
}
// 排序
if (payload.FirstSort != null)
{
// 验证排序字段是否有效
var validFields = new[] { "Id", "Name", "IP", "Notice", "IsDeleted", "CreateTime", "UpdateTime" };
if (!string.IsNullOrEmpty(payload.FirstSort.Field) && validFields.Contains(payload.FirstSort.Field))
{
query = query.OrderBy(payload.FirstSort.Field, payload.FirstSort.Direct == "DESC");
}
}
// 先获取总数
var totalCount = query.Count();
// 获取分页数据
var list = query.Paged(payload.CurrentPage, payload.PageSize).ToList();
// 获取所有相关ID
var nvrIds = list.Select(x => x.Id).ToList();
// 批量查询摄像头数量
var cameraCounts = _dbContext.Camera
.Where(c => nvrIds.Contains(c.NvrServerId) && c.IsDeleted == IsDeleted.No)
.GroupBy(c => c.NvrServerId)
.ToDictionary(g => g.Key, g => g.Count());
// 在 using 块内完成所有数据映射
var data = list.Select(x =>
{
var model = _mapper.Map<DncZeus.Api.Entities.NvrServer, NvrServerJsonModel>(x);
model.CreateTime = x.CreateTime.ToString("yyyy-MM-dd HH:mm:ss");
model.UpdateTime = x.UpdateTime?.ToString("yyyy-MM-dd HH:mm:ss");
model.CameraCount = cameraCounts.GetValueOrDefault(x.Id, 0);
return model;
}).ToList();
var response = ResponseModelFactory.CreateResultInstance;
response.SetData(data, totalCount);
return Ok(response);
}
}
// 测试接口,返回所有的数据(不分页)
[HttpGet("debug")]
public IActionResult GetAllDebug()
{
using (_dbContext)
{
var allRecords = _dbContext.NvrServer
.Select(x => new { x.Id, x.Name, x.IsDeleted, x.CreateTime })
.ToList();
var response = ResponseModelFactory.CreateInstance;
response.SetData(new { AllRecords = allRecords, TotalCount = allRecords.Count });
return Ok(response);
}
}
// create接口
[HttpPost]
public IActionResult Create(NvrServerCreateViewModel model)
{
var response = ResponseModelFactory.CreateInstance;
using (_dbContext)
{
if (_dbContext.NvrServer.Any(x => x.Name == model.Name.Trim()))
{
response.SetFailed("服务器名称已存在");
return Ok(response);
}
if (_dbContext.NvrServer.Any(x => x.IP == model.IP.Trim()))
{
response.SetFailed("IP地址已存在");
return Ok(response);
}
/*利用mapper快速生成entity(若校验不通过会自动触发异常,无需再try)
{
"errors": {
"IP": [
"请输入IP地址"
]
},
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "00-b80c95c5799d733934eb6ac53c69025c-6787641c69bfb97c-00"
}
*/
var entity = _mapper.Map<NvrServerCreateViewModel, Entities.NvrServer>(model);
entity.CreateTime = DateTime.Now;
entity.IsDeleted = IsDeleted.No;
_dbContext.NvrServer.Add(entity);
_dbContext.SaveChanges();
response.SetSuccess();
return Ok(response);
}
}
// 获取单个实体
[HttpGet("{id}")]
public IActionResult Edit(int id) {
var entity = _dbContext.NvrServer.FirstOrDefault(x => x.Id == id);
if (entity == null) {
return NotFound();
}
var response = ResponseModelFactory.CreateInstance;
response.SetData(_mapper.Map<Entities.NvrServer,NvrServerEditViewModel>(entity));
return Ok(response);
}
[HttpPost]
public IActionResult Edit(NvrServerEditViewModel model)
{
var response = ResponseModelFactory.CreateInstance;
using (_dbContext) {
var entity = _dbContext.NvrServer.FirstOrDefault(x => x.Id == model.Id);
if (entity == null)
{
response.SetFailed("服务器不存在");
return Ok(response);
}
if (_dbContext.NvrServer.Any(x => x.Name == model.Name.Trim() && x.Id != model.Id))
{
response.SetFailed("服务器名称已存在");
return Ok(response);
}
if (_dbContext.NvrServer.Any(x => x.IP == model.IP.Trim() && x.Id != model.Id))
{
response.SetFailed("IP地址已存在");
return Ok(response);
}
entity.Name = model.Name;
entity.IP = model.IP;
entity.Notice = model.Notice;
// entity.IsDeleted = model.IsDeleted;
entity.IsDeleted = model.IsDeleted ? CommonEnum.IsDeleted.Yes : CommonEnum.IsDeleted.No;
entity.UpdateTime = DateTime.Now;
_dbContext.SaveChanges();
response.SetSuccess();
return Ok(response);
}
}
[HttpGet("{ids}")]
public IActionResult Delete(string ids)
{
var response = UpdateIsDelete(IsDeleted.Yes, ids);
return Ok(response);
}
[HttpGet("{ids}")]
public IActionResult Recover(string ids)
{
var response = UpdateIsDelete(IsDeleted.No, ids);
return Ok(response);
}
[HttpGet]
public IActionResult GetAll()
{
using (_dbContext)
{
var list = _dbContext.NvrServer
.Where(x => x.IsDeleted == IsDeleted.No)
.Select(x => new { x.Id, x.Name })
.ToList();
var response = ResponseModelFactory.CreateInstance;
response.SetData(list);
return Ok(response);
}
}
// 批量删除
private ResponseModel UpdateIsDelete(IsDeleted isDeleted, string ids)
{
var response = ResponseModelFactory.CreateInstance;
var idList = ids.Split(",").Select(x => int.Parse(x)).ToList();
using (_dbContext)
{
var servers = _dbContext.NvrServer.Where(x => idList.Contains(x.Id)).ToList();
foreach (var server in servers)
{
server.IsDeleted = isDeleted;
server.UpdateTime = DateTime.Now;
}
_dbContext.SaveChanges();
return response;
}
}
}
}
Edit接口代码优化
- 针对
public IActionResult Edit(NvrServerEditViewModel model)接口里面的手动赋值,这里可以利用mapper实现更简洁的代码
// MappingProfile.cs
......
// 新增
CreateMap<NvrServerEditViewModel, NvrServer>()
.ForMember(dest => dest.CreateTime, opt => opt.Ignore())
.ForMember(dest => dest.UpdateTime, opt => opt.Ignore())
.ForMember(dest => dest.IsDeleted, opt => opt.MapFrom(src => src.IsDeleted ? IsDeleted.Yes : IsDeleted.No));
// 原先
CreateMap<NvrServer, NvrServerEditViewModel>()
.ForMember(dest => dest.IsDeleted, opt => opt.MapFrom(src => src.IsDeleted==IsDeleted.Yes));
// 接口.cs
public IActionResult Edit(NvrServerEditViewModel model)
{
......
using (_dbContext) {
var entity = _dbContext.NvrServer.FirstOrDefault(x => x.Id == model.Id);
......
//entity.Name = model.Name;
//entity.IP = model.IP;
//entity.Notice = model.Notice;
////entity.IsDeleted = model.IsDeleted;
//entity.IsDeleted = model.IsDeleted ? CommonEnum.IsDeleted.Yes : CommonEnum.IsDeleted.No;
//entity.UpdateTime = DateTime.Now;
// 使用AutoMapper映射到现有实体
_mapper.Map(model, entity);
// 手动赋值(不想赋值也可以,mapper再做一个配置即可)
entity.UpdateTime = DateTime.Now;
_dbContext.SaveChanges();
response.SetSuccess();
return Ok(response);
}
}
Camera模型CRUD演示
// 实体类.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using static DncZeus.Api.Entities.Enums.CommonEnum;
namespace DncZeus.Api.Entities
{
public class Camera
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
[StringLength(100)]
public string Name { get; set; }
[Required]
[StringLength(45)] // IPv6最大长度
public string IP { get; set; }
[StringLength(100)]
public string Notice { get; set; }
[Range(1, 16, ErrorMessage = "通道号必须在1-16之间")]
public int Channel { get; set; }
[Required]
public int NvrServerId { get; set; }
[ForeignKey("NvrServerId")]
public virtual NvrServer NvrServer { get; set; }
public IsDeleted IsDeleted { get; set; }
public DateTime CreateTime { get; set; }
public DateTime? UpdateTime { get; set; }
}
}
// dbContext.cs
......
public DbSet<Camera> Camera { get; set; }
......
modelBuilder.Entity<Camera>(entity =>
{
entity.HasKey(e => e.Id);
entity.Property(e => e.Name).IsRequired();
entity.Property(e => e.IP).IsRequired();
entity.Property(e => e.Channel).IsRequired();
entity.HasOne(c => c.NvrServer) // 设置一端
.WithMany(n => n.Cameras) // 设置多端
.HasForeignKey(c => c.NvrServerId) // 外键以及级联关系
.OnDelete(DeleteBehavior.Cascade);
});
自定义校验特性ValidaCameraAttribute
- 作用: 校验
实体类的CRUD操作[这里只写新增和编辑校验]中,字段是否合法
// ViewModels.Equitments.Camera.ValidationAttributes.ValidaCameraAttribute.cs
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using DncZeus.Api.Entities;
using DncZeus.Api.Entities.Enums;
namespace DncZeus.Api.ViewModels.Equitments.Camera.ValidationAttributes
{
/// <summary>
/// 摄像头名称唯一性验证特性
/// </summary>
public class ValidaCameraAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var dbContext = (DncZeusDbContext)validationContext.GetService(typeof(DncZeusDbContext));
var model = validationContext.ObjectInstance as CameraCreateViewModel;
// 检查value是否为null或空字符串
if (value == null || string.IsNullOrWhiteSpace(value.ToString()))
{
return ValidationResult.Success; // 校验假装成功,让后续Required验证特性处理这个错误
}
if (dbContext?.Camera.Any(x => x.Name == value.ToString().Trim() &&
x.NvrServerId == model.NvrServerId &&
x.IsDeleted == CommonEnum.IsDeleted.No) == true)
{
return new ValidationResult("同一NVR服务器下摄像头名称已存在");
}
return ValidationResult.Success;
}
}
/// <summary>
/// IP地址唯一性验证特性
/// </summary>
public class UniqueIPAddressAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var dbContext = (DncZeusDbContext)validationContext.GetService(typeof(DncZeusDbContext));
if (value == null || string.IsNullOrWhiteSpace(value.ToString()))
{
return ValidationResult.Success;
}
if (dbContext?.Camera.Any(x => x.IP == value.ToString().Trim() &&
x.IsDeleted == CommonEnum.IsDeleted.No) == true)
{
return new ValidationResult("IP地址已存在");
}
return ValidationResult.Success;
}
}
/// <summary>
/// 通道号唯一性验证特性
/// </summary>
public class UniqueChannelAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var dbContext = (DncZeusDbContext)validationContext.GetService(typeof(DncZeusDbContext));
var model = validationContext.ObjectInstance as CameraCreateViewModel;
if (value == null)
{
return ValidationResult.Success;
}
if (dbContext?.Camera.Any(x => x.Channel == (int)value &&
x.NvrServerId == model.NvrServerId &&
x.IsDeleted == CommonEnum.IsDeleted.No) == true)
{
return new ValidationResult($"通道号{value}已被占用");
}
return ValidationResult.Success;
}
}
/// <summary>
/// NVR服务器有效性验证特性
/// </summary>
public class ValidNvrServerAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var dbContext = (DncZeusDbContext)validationContext.GetService(typeof(DncZeusDbContext));
var nvrServerId = (int)value;
if (dbContext?.NvrServer.Any(x => x.Id == nvrServerId &&
x.IsDeleted == CommonEnum.IsDeleted.No) != true)
{
return new ValidationResult("所选的NVR服务器不存在");
}
return ValidationResult.Success;
}
}
/// <summary>
/// 摄像头ID有效性验证特性(编辑时使用,优先验证)
/// </summary>
public class ValidCameraIdAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var cameraId = (int)value;
if (cameraId <= 0)
{
return new ValidationResult("请选择要编辑的摄像头");
}
var dbContext = (DncZeusDbContext)validationContext.GetService(typeof(DncZeusDbContext));
if (dbContext?.Camera.Any(x => x.Id == cameraId &&
x.IsDeleted == CommonEnum.IsDeleted.No) != true)
{
return new ValidationResult("所选的摄像头不存在");
}
return ValidationResult.Success;
}
}
/// <summary>
/// 摄像头名称唯一性验证特性(编辑时使用,排除当前记录)
/// </summary>
public class UniqueCameraNameEditAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var dbContext = (DncZeusDbContext)validationContext.GetService(typeof(DncZeusDbContext));
var model = validationContext.ObjectInstance as CameraEditViewModel;
if (value == null || string.IsNullOrWhiteSpace(value.ToString()))
{
return ValidationResult.Success;
}
// 首先验证摄像头ID是否存在
if (model.Id <= 0 || !dbContext.Camera.Any(x => x.Id == model.Id && x.IsDeleted == CommonEnum.IsDeleted.No))
{
return ValidationResult.Success; // 让ValidCameraIdAttribute处理这个错误
}
if (dbContext?.Camera.Any(x => x.Name == value.ToString().Trim() &&
x.NvrServerId == model.NvrServerId &&
x.Id != model.Id &&
x.IsDeleted == CommonEnum.IsDeleted.No) == true)
{
return new ValidationResult("同一NVR服务器下摄像头名称已存在");
}
return ValidationResult.Success;
}
}
/// <summary>
/// IP地址唯一性验证特性(编辑时使用,排除当前记录)
/// </summary>
public class UniqueIPAddressEditAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var dbContext = (DncZeusDbContext)validationContext.GetService(typeof(DncZeusDbContext));
var model = validationContext.ObjectInstance as CameraEditViewModel;
// 检查value是否为null或空字符串
if (value == null || string.IsNullOrWhiteSpace(value.ToString()))
{
return ValidationResult.Success;
}
// 首先验证摄像头ID是否存在
if (model.Id <= 0 || !dbContext.Camera.Any(x => x.Id == model.Id && x.IsDeleted == CommonEnum.IsDeleted.No))
{
return ValidationResult.Success;
}
if (dbContext?.Camera.Any(x => x.IP == value.ToString().Trim() &&
x.Id != model.Id &&
x.IsDeleted == CommonEnum.IsDeleted.No) == true)
{
return new ValidationResult("IP地址已存在");
}
return ValidationResult.Success;
}
}
/// <summary>
/// 通道号唯一性验证特性(编辑时使用,排除当前记录)
/// </summary>
public class UniqueChannelEditAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var dbContext = (DncZeusDbContext)validationContext.GetService(typeof(DncZeusDbContext));
var model = validationContext.ObjectInstance as CameraEditViewModel;
// 检查value是否为null
if (value == null)
{
return ValidationResult.Success;
}
// 首先验证摄像头ID是否存在
if (model.Id <= 0 || !dbContext.Camera.Any(x => x.Id == model.Id && x.IsDeleted == CommonEnum.IsDeleted.No))
{
return ValidationResult.Success;
}
if (dbContext?.Camera.Any(x => x.Channel == (int)value &&
x.NvrServerId == model.NvrServerId &&
x.Id != model.Id &&
x.IsDeleted == CommonEnum.IsDeleted.No) == true)
{
return new ValidationResult($"通道号{value}已被占用");
}
return ValidationResult.Success;
}
}
}
- 这里对这个
.net框架特性要有一个理解
- 无法控制验证特性的执行顺序!
- 因为增加框架复杂度,并且需要维护验证优先级机制
ViewModel模型(序列化模型)
- 自定义三个模型,分别负责
新增,编辑和响应的JSON对象
- CameraCreateViewModel
- CameraEditViewModel
- CameraJsonModel
using System;
using System.ComponentModel.DataAnnotations;
using DncZeus.Api.Entities.Enums;
using DncZeus.Api.ViewModels.Equitments.Camera.ValidationAttributes;
namespace DncZeus.Api.ViewModels.Equitments.Camera
{
public class CameraCreateViewModel
{
[ValidaCamera(ErrorMessage = "同一NVR服务器下摄像头名称已存在")]
[Required(ErrorMessage = "请输入摄像头名称")]
[StringLength(100, ErrorMessage = "摄像头名称长度不能超过100个字符")]
public string Name { get; set; }
[Required(ErrorMessage = "请输入IP地址")]
[StringLength(45, ErrorMessage = "IP地址长度不能超过45个字符")]
[UniqueIPAddress(ErrorMessage = "IP地址已存在")]
public string IP { get; set; }
[StringLength(100, ErrorMessage = "备注长度不能超过100个字符")]
public string Notice { get; set; }
[Required(ErrorMessage = "请输入通道号")]
[Range(1, 16, ErrorMessage = "通道号必须在1-16之间")]
[UniqueChannel(ErrorMessage = "通道号已被占用")]
public int Channel { get; set; }
[Required(ErrorMessage = "请选择NVR服务器")]
[ValidNvrServer(ErrorMessage = "所选的NVR服务器不存在")]
public int NvrServerId { get; set; }
// 自动赋值字段 - 不需要前端传递
public DateTime CreateTime { get; set; } = DateTime.Now;
public DateTime? UpdateTime { get; set; } = DateTime.Now;
public bool IsDeleted { get; set; } = false;
}
}
......
using System.ComponentModel.DataAnnotations;
using DncZeus.Api.ViewModels.Equitments.Camera.ValidationAttributes;
namespace DncZeus.Api.ViewModels.Equitments.Camera
{
public class CameraEditViewModel
{
[ValidCameraId(ErrorMessage = "所选的摄像头不存在")]
public int Id { get; set; }
[Required(ErrorMessage = "请输入摄像头名称")]
[StringLength(100, ErrorMessage = "摄像头名称长度不能超过100个字符")]
[UniqueCameraNameEdit(ErrorMessage = "同一NVR服务器下摄像头名称已存在")]
public string Name { get; set; }
[Required(ErrorMessage = "请输入IP地址")]
[StringLength(45, ErrorMessage = "IP地址长度不能超过45个字符")]
[UniqueIPAddressEdit(ErrorMessage = "IP地址已存在")]
public string IP { get; set; }
[StringLength(100, ErrorMessage = "备注长度不能超过100个字符")]
public string Notice { get; set; }
[Required(ErrorMessage = "请输入通道号")]
[Range(1, 16, ErrorMessage = "通道号必须在1-16之间")]
[UniqueChannelEdit(ErrorMessage = "通道号已被占用")]
public int Channel { get; set; }
[Required(ErrorMessage = "请选择NVR服务器")]
[ValidNvrServer(ErrorMessage = "所选的NVR服务器不存在")]
public int NvrServerId { get; set; }
public bool IsDeleted { get; set; }
}
}
......
namespace DncZeus.Api.ViewModels.Equitments.Camera
{
public class CameraJsonModel
{
public int Id { get; set; }
public string Name { get; set; }
public string IP { get; set; }
public string Notice { get; set; }
public int Channel { get; set; }
public int NvrServerId { get; set; }
public string NvrServerName { get; set; }
public bool IsDeleted { get; set; }
public string CreateTime { get; set; }
public string UpdateTime { get; set; }
}
}
ViewModel和实体类之间作映射Map
using AutoMapper;
using DncZeus.Api.Entities;
using DncZeus.Api.Entities.QueryModels;
using DncZeus.Api.ViewModels.Equitments.Camera;
using DncZeus.Api.ViewModels.Equitments.NvrServer;
using DncZeus.Api.ViewModels.Rbac.DncIcon;
using DncZeus.Api.ViewModels.Rbac.DncMenu;
using DncZeus.Api.ViewModels.Rbac.DncPermission;
using DncZeus.Api.ViewModels.Rbac.DncRole;
using DncZeus.Api.ViewModels.Rbac.DncUser;
using static DncZeus.Api.Entities.Enums.CommonEnum;
namespace DncZeus.Api.Configurations
{
/// <summary>
///
/// </summary>
public class MappingProfile : Profile
{
/// <summary>
///
/// </summary>
public MappingProfile()
{
......
#region NvrServer
CreateMap<NvrServer, NvrServerJsonModel>()
.ForMember(dest => dest.IsDeleted, opt => opt.MapFrom(src => src.IsDeleted == IsDeleted.Yes));
CreateMap<NvrServerCreateViewModel, NvrServer>();
CreateMap<NvrServerEditViewModel, NvrServer>()
.ForMember(dest => dest.CreateTime, opt => opt.Ignore())
.ForMember(dest => dest.UpdateTime, opt => opt.Ignore())
.ForMember(dest => dest.IsDeleted, opt => opt.MapFrom(src => src.IsDeleted ? IsDeleted.Yes : IsDeleted.No));
CreateMap<NvrServer, NvrServerEditViewModel>()
.ForMember(dest => dest.IsDeleted, opt => opt.MapFrom(src => src.IsDeleted==IsDeleted.Yes));
#endregion
#region Camera
CreateMap<Camera, CameraJsonModel>()
.ForMember(dest => dest.IsDeleted, opt => opt.MapFrom(src => src.IsDeleted == IsDeleted.Yes));
// CreateMap<CameraCreateViewModel, Camera>();
CreateMap<CameraCreateViewModel, Camera>()
.ForMember(dest => dest.IsDeleted, opt => opt.MapFrom(src => src.IsDeleted ? IsDeleted.Yes : IsDeleted.No));
CreateMap<Camera, CameraEditViewModel>()
.ForMember(dest => dest.IsDeleted, opt => opt.MapFrom(src => src.IsDeleted == IsDeleted.Yes));
CreateMap<CameraEditViewModel, Camera>()
.ForMember(dest => dest.IsDeleted, opt => opt.MapFrom(src => src.IsDeleted ? IsDeleted.Yes : IsDeleted.No));
#endregion
}
}
}
接口代码如下
using AutoMapper;
using DncZeus.Api.Entities;
using DncZeus.Api.Entities.Enums;
using DncZeus.Api.Extensions;
using DncZeus.Api.Extensions.AuthContext;
using DncZeus.Api.Extensions.DataAccess;
using DncZeus.Api.Models.Response;
using DncZeus.Api.RequestPayload.Equitments.NvrServer;
using DncZeus.Api.RequestPayload.Equitments.Camera;
using DncZeus.Api.ViewModels.Equitments.NvrServer;
using DncZeus.Api.ViewModels.Equitments.Camera;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Linq;
using static DncZeus.Api.Entities.Enums.CommonEnum;
using Microsoft.EntityFrameworkCore;
namespace DncZeus.Api.Controllers.Api.V1.Equitments.Camera
{
[Route("api/v1/camera/[action]")]
[ApiController]
public class CameraController : ControllerBase
{
private readonly DncZeusDbContext _dbContext;
private readonly IMapper _mapper;
public CameraController(DncZeusDbContext dbContext, IMapper mapper)
{
_dbContext = dbContext;
_mapper = mapper;
}
[HttpPost]
public IActionResult Create(CameraCreateViewModel model)
{
var response = ResponseModelFactory.CreateInstance;
using (_dbContext)
{
//if (_dbContext.Camera.Any(x => x.Name == model.Name.Trim() && x.NvrServerId == model.NvrServerId))
//{
// response.SetFailed("同一NVR服务器下摄像头名称已存在");
// return Ok(response);
//}
//if (_dbContext.Camera.Any(x => x.IP == model.IP.Trim()))
//{
// response.SetFailed("IP地址已存在");
// return Ok(response);
//}
//if (_dbContext.Camera.Any(x => x.Channel == model.Channel && x.NvrServerId == model.NvrServerId))
//{
// response.SetFailed($"通道号{model.Channel}已被占用");
// return Ok(response);
//}
// ASP.NET Core会自动执行模型验证,我们只需要检查ModelState
if (!ModelState.IsValid)
{
var firstError = ModelState.Values.SelectMany(v => v.Errors).FirstOrDefault()?.ErrorMessage;
response.SetFailed(firstError ?? "数据验证失败");
return Ok(response);
}
//var entity = _mapper.Map<CameraCreateViewModel, Entities.Camera>(model);
//entity.CreateTime = DateTime.Now;
//entity.UpdateTime = DateTime.Now;
//entity.IsDeleted = IsDeleted.No;
var entity = _mapper.Map<CameraCreateViewModel, Entities.Camera>(model);
_dbContext.Camera.Add(entity);
_dbContext.SaveChanges();
response.SetSuccess();
return Ok(response);
}
}
[HttpGet("{id}")]
public IActionResult Edit(int id)
{
using (_dbContext) {
var entity = _dbContext.Camera.Include("NvrServer").FirstOrDefault(x => x.Id == id);
if (entity == null)
{
return NotFound();
}
var response = ResponseModelFactory.CreateInstance;
response.SetData(_mapper.Map<Entities.Camera, CameraEditViewModel>(entity));
return Ok(response);
}
}
[HttpPost]
public IActionResult Edit(CameraEditViewModel model)
{
var response = ResponseModelFactory.CreateInstance;
using (_dbContext)
{
//if (_dbContext.Camera.Any(x => x.Name == model.Name.Trim() && x.NvrServerId == model.NvrServerId))
//{
// response.SetFailed("同一NVR服务器下摄像头名称已存在");
// return Ok(response);
//}
//if (_dbContext.Camera.Any(x => x.IP == model.IP.Trim()))
//{
// response.SetFailed("IP地址已存在");
// return Ok(response);
//}
//if (_dbContext.Camera.Any(x => x.Channel == model.Channel && x.NvrServerId == model.NvrServerId))
//{
// response.SetFailed($"通道号{model.Channel}已被占用");
// return Ok(response);
//}
// ASP.NET Core会自动执行模型验证,我们只需要检查ModelState
if (!ModelState.IsValid)
{
var firstError = ModelState.Values.SelectMany(v => v.Errors).FirstOrDefault()?.ErrorMessage;
response.SetFailed(firstError ?? "数据验证失败");
return Ok(response);
}
var entity = _dbContext.Camera.FirstOrDefault(x => x.Id == model.Id);
//var entity = _mapper.Map<CameraCreateViewModel, Entities.Camera>(model);
//entity.CreateTime = DateTime.Now;
//entity.UpdateTime = DateTime.Now;
//entity.IsDeleted = IsDeleted.No;
_mapper.Map(model, entity);
_dbContext.SaveChanges();
response.SetSuccess();
return Ok(response);
}
}
[HttpPost]
public IActionResult List(CameraRequestPayload payload)
{
using (_dbContext)
{
var query = _dbContext.Camera.Include("NvrServer").AsQueryable();
if (!string.IsNullOrEmpty(payload.Kw))
{
query = query.Where(x => x.Name.Contains(payload.Kw.Trim()) ||
x.IP.Contains(payload.Kw.Trim()) ||
(x.Notice != null && x.Notice.Contains(payload.Kw.Trim())));
}
if (payload.IsDeleted > IsDeleted.All)
{
query = query.Where(x => x.IsDeleted == payload.IsDeleted);
}
if (payload.NvrServerId.HasValue)
{
query = query.Where(x => x.NvrServerId == payload.NvrServerId.Value);
}
if (payload.FirstSort != null)
{
query = query.OrderBy(payload.FirstSort.Field, payload.FirstSort.Direct == "DESC");
}
var list = query.Paged(payload.CurrentPage, payload.PageSize).ToList();
var totalCount = query.Count();
var data = list.Select(x =>
{
var model = _mapper.Map<Entities.Camera, CameraJsonModel>(x);
model.CreateTime = x.CreateTime.ToString("yyyy-MM-dd HH:mm:ss");
model.UpdateTime = x.UpdateTime?.ToString("yyyy-MM-dd HH:mm:ss");
model.NvrServerName = x.NvrServer?.Name;
return model;
});
var response = ResponseModelFactory.CreateResultInstance;
response.SetData(data, totalCount);
return Ok(response);
}
}
[HttpGet("{ids}")]
public IActionResult Delete(string ids)
{
var response = UpdateIsDelete(IsDeleted.Yes, ids);
return Ok(response);
}
[HttpGet("{ids}")]
public IActionResult Recover(string ids)
{
var response = UpdateIsDelete(IsDeleted.No, ids);
return Ok(response);
}
private ResponseModel UpdateIsDelete(IsDeleted isDeleted, string ids)
{
var response = ResponseModelFactory.CreateInstance;
// 校验ids参数
if (string.IsNullOrWhiteSpace(ids))
{
response.SetFailed("请选择要操作的摄像头");
return response;
}
try
{
var idLists = ids.Split(",", StringSplitOptions.RemoveEmptyEntries)
.Select(x => int.Parse(x.Trim()))
.ToList();
if (!idLists.Any())
{
response.SetFailed("请选择要操作的摄像头");
return response;
}
}
catch (Exception)
{
response.SetFailed("摄像头ID格式不正确");
return response;
}
var idList = ids.Split(",", StringSplitOptions.RemoveEmptyEntries)
.Select(x => int.Parse(x.Trim()))
.ToList();
using (_dbContext)
{
var cameras = _dbContext.Camera.Where(x => idList.Contains(x.Id)).ToList();
if (!cameras.Any())
{
response.SetFailed("未找到指定的摄像头");
return response;
}
foreach (var camera in cameras)
{
camera.IsDeleted = isDeleted;
camera.UpdateTime = DateTime.Now;
}
_dbContext.SaveChanges();
return response;
}
}
}
}

浙公网安备 33010602011771号