在.NET Core WebAPI中应当在哪里实现业务逻辑?
发票应用Repository层实现方案参考
核心结论
是否需要单独实现Repository层没有统一标准,可根据项目实际情况选择:
- 中小规模、无强扩展性需求的项目可以直接用EF DbContext,不需要额外封装Repository层
- 大规模、有复杂业务规则和测试需求的项目建议实现Repository层
不需要实现Repository层的场景
- 项目体量小,业务逻辑简单,后续没有更换ORM框架、切换数据库类型的规划
EF本身已经内置了仓储和工作单元的实现,直接在业务服务层注入DbContext即可完成数据操作。你需要的自动生成发票编号逻辑可以直接在业务层实现:先读取对应批次的最新发票编号,累加后赋值给新发票实体,调用DbContext.AddAsync()插入后执行SaveChangesAsync()即可,额外封装Repository层只会增加冗余代码,降低开发效率。 - 项目没有单元测试、统一数据操作切面(如统一软删除过滤、操作日志埋点)的需求,直接使用DbContext的开发成本更低。
建议实现Repository层的场景
- 项目规模大,业务迭代频繁,后续有扩展可能性
Repository层可以隔离底层数据访问实现,上层业务逻辑不需要感知底层用的是EF还是其他ORM,后续更换数据访问组件时只需要修改Repository层的实现,不需要改动上层业务代码。 - 需要对数据操作做统一管控
比如所有发票查询默认过滤已作废数据、插入操作统一做编号重复校验,把这类通用逻辑放在Repository层可以避免业务层出现重复代码,符合单一职责原则。 - 有单元测试需求
Repository层可以很方便的做Mock,不需要依赖真实数据库即可完成业务逻辑的单元测试。
发票编号生成的注意事项
不管是否实现Repository层,都要避免高并发场景下的编号重复问题,不要直接用内存读取最大编号+1的生成方式,推荐两种方案:
- 数据库层面创建序列或者唯一约束,由数据库保证编号的唯一性,应用层直接读取生成后的编号
- 生成编号时加分布式锁,同时在数据库表的编号字段加唯一索引,捕获重复插入异常后自动重试
内容的提问来源于stack exchange,提问作者Alex Ivan
相关产品推荐
相关产品推荐

