ASP.NET中避免重复邮箱的实现依赖异常捕获,求更优方案
优化方案
1. 重构GetByEmailAsync方法
直接使用FirstOrDefaultAsync替代FirstAsync——这个方法在没有匹配文档时会返回null,完全不需要捕获异常,这才是处理“无匹配数据”这类正常业务场景的正确方式:
public async Task<Shopper?> GetByEmailAsync(string email) { return await _shoppersCollection.Find(x => x.Email == email).FirstOrDefaultAsync(); }
2. 简化ValidateEmail方法
原方法的逻辑可以简化为一行代码,直接判断查询结果是否非空:
public async Task<bool> ValidateEmail(string email) { return await GetByEmailAsync(email) != null; }
3. 控制器方法优化
去掉多余的空合并运算符!,因为ValidateEmail返回的Task<bool>在await后就是明确的布尔值:
[HttpPost] public async Task<IActionResult> Post(Shopper newShopper) { if (await _shoppersService.ValidateEmail(newShopper.Email)) return StatusCode(409, new { message = "Email is already in use." }); await _shoppersService.CreateAsync(newShopper); return CreatedAtAction(nameof(Get), new { id = newShopper.Id }, newShopper); }
额外建议
数据库层面加唯一约束:上述代码在高并发场景下可能存在竞态条件(比如两个请求同时验证同一邮箱都通过,随后都执行创建操作)。因此必须在MongoDB的
Email字段上创建唯一索引,从数据库层面强制保证邮箱不重复。初始化时可执行以下代码创建索引:await _shoppersCollection.Indexes.CreateOneAsync( new CreateIndexModel<Shopper>( Builders<Shopper>.IndexKeys.Ascending(x => x.Email), new CreateIndexOptions { Unique = true } ) );此时若插入重复邮箱,数据库会抛出唯一键冲突异常,你只需在
CreateAsync方法中捕获该特定异常并返回对应错误即可——这种场景下的异常才属于真正的意外情况。简化调用链:如果
ValidateEmail方法仅用于判断邮箱是否存在,可直接在控制器中调用GetByEmailAsync,省去中间层让逻辑更直接:[HttpPost] public async Task<IActionResult> Post(Shopper newShopper) { var existingShopper = await _shoppersService.GetByEmailAsync(newShopper.Email); if (existingShopper != null) return StatusCode(409, new { message = "Email is already in use." }); await _shoppersService.CreateAsync(newShopper); return CreatedAtAction(nameof(Get), new { id = newShopper.Id }, newShopper); }
内容的提问来源于stack exchange,提问作者Literal Garbage
相关产品推荐
相关产品推荐

