POST方法插入数据时如何仅通过代码实现Code字段唯一性校验
现有代码结构
模型类
public class SDN { [Key] public int Id { get; set; } public int Codigo {get; set;} public string nit { get; set; } public string nombre { get; set; } public string telefono1 { get; set; } public string telefono2 { get; set; } public string direccion { get; set; } public string email { get; set; } public string codciudad { get; set; } public string codtipo { get; set; } }
DTO类
public class SdnDTO { public int Id { get; set; } public int Code { get; set; } [Required(ErrorMessage = "The field SDN Nit is required ")] public string nit { get; set; } [Required(ErrorMessage = "The field SDN Nombre is required ")] public string nombre { get; set; } public string telefono1 { get; set; } public string telefono2 { get; set; } public string direccion { get; set; } public string email { get; set; } public string codciudad { get; set; } public string codtipo { get; set; } }
仓储层插入方法
public async Task<TEntity> Insert(TEntity entity) { try { centralContext.Set<TEntity>().Add(entity); await centralContext.SaveChangesAsync(); return entity; } catch (Exception ex) { throw ex; } }
服务层插入方法
public async Task<TEntity> Insert(TEntity entity) { return await genericRepository.Insert(entity); }
控制器插入接口
/// <summary> /// 插入方法 /// </summary> /// <param name="sdnDTO"></param> /// <returns></returns> [HttpPost] public async Task<IHttpActionResult> Post(SdnDTO sdnDTO) { if (!ModelState.IsValid) return BadRequest(ModelState); try { var sdn = mapper.Map<SDN>(sdnDTO); sdn = await sdnService.Insert(sdn); return Ok(sdn); } catch (Exception ex) { return InternalServerError(ex); } }
业务层实现Code唯一校验的方案
你需要校验的DTO的Code字段对应模型类的Codigo字段,无需修改数据库,仅调整业务代码的实现步骤如下:
- 先在仓储层新增通用存在性校验方法
在你的泛型仓储类中添加如下方法,用于判断符合指定条件的记录是否存在:
using System.Linq.Expressions; // 泛型仓储新增方法 public async Task<bool> ExistsAsync(Expression<Func<TEntity, bool>> predicate) { return await centralContext.Set<TEntity>().AnyAsync(predicate); }
- 服务层同步暴露该方法,泛型服务直接继承仓储方法即可
- 在插入逻辑中添加校验
推荐将校验逻辑放在服务层,符合业务逻辑下沉的规范,如果你有SDN专属的服务类,可重写Insert方法:
// SDN专属服务类重写Insert方法 public async Task<SDN> Insert(SDN entity) { // 校验Codigo是否已存在 var isDuplicate = await ExistsAsync(s => s.Codigo == entity.Codigo); if (isDuplicate) { throw new InvalidOperationException("当前提交的Code值已存在,无法重复插入"); } return await base.Insert(entity); }
如果不想调整服务层,也可以直接在控制器中添加校验逻辑:
[HttpPost] public async Task<IHttpActionResult> Post(SdnDTO sdnDTO) { if (!ModelState.IsValid) return BadRequest(ModelState); try { var sdn = mapper.Map<SDN>(sdnDTO); // 新增Code重复校验 var codeExists = await sdnService.ExistsAsync<SDN>(s => s.Codigo == sdn.Codigo); if (codeExists) { return BadRequest("提交的Code值已存在,请勿重复提交"); } sdn = await sdnService.Insert(sdn); return Ok(sdn); } catch (Exception ex) { return InternalServerError(ex); } }
注意:该方案为业务层单实例校验,高并发场景下仍有极低概率出现重复插入,后续允许修改数据库时,建议给
Codigo字段添加唯一索引做双层保障。另外请确认你的AutoMapper配置中已经正确配置了SdnDTO.Code到SDN.Codigo的映射关系,避免校验字段不匹配的问题。
内容的提问来源于stack exchange,提问作者Hackerman
相关产品推荐
相关产品推荐

