You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在CQRS .NET API中创建实体仓库且避免持久层依赖领域层?

解决CQRS .NET API分层依赖的可行方案

针对你遇到的「持久层需操作领域实体但不想直接依赖领域层」的问题,以下是几个落地性强的解决方案:

方案1:优化你提出的实体契约分层思路

不用单独新建独立的Domain.EntityInterfaces层,而是在领域层内部拆分出一个轻量契约子项目(比如Domain.Contracts),只存放实体的核心标识和公共契约,不包含领域业务逻辑:

  • 具体步骤:
    1. 创建Domain.Contracts项目,定义基础实体接口:
      public interface IEntity
      {
          int Id { get; }
      }
      
    2. 领域层的User实体实现该接口:
      public class User : IEntity
      {
          public int Id { get; private set; }
          // 其他领域属性、业务方法
      }
      
    3. 应用层的仓库接口基于IEntity定义:
      public interface IUserRepository
      {
          Task<IEntity> GetByIdAsync(int id);
          Task AddAsync(IEntity entity);
      }
      
    4. 持久层仅引用Domain.Contracts项目,实现仓库接口时,内部通过ORM(比如EF Core)完成数据库映射,将数据库实体转换为IEntity返回给应用层。
    5. 应用层同时引用领域层和Domain.Contracts,在拿到IEntity后,转换为完整的User实体用于领域逻辑处理。

这个方案的优势是既保持了领域实体的契约一致性,又避免了持久层直接依赖完整领域层。

方案2:用DTO做中间层完全隔离依赖

彻底切断持久层与领域层的关联,通过应用层定义的DTO作为数据传输载体:

  • 具体步骤:
    1. 在应用层定义UserDto(仅包含持久化所需字段)和仓库接口:
      public class UserDto
      {
          public int Id { get; set; }
          public string Username { get; set; }
          // 其他需要持久化的字段
      }
      
      public interface IUserRepository
      {
          Task<UserDto> GetByIdAsync(int id);
          Task AddAsync(UserDto dto);
      }
      
    2. 持久层实现仓库接口,直接操作UserDto与数据库交互(比如用EF Core将UserDto映射为数据库表实体,或用ADO.NET直接读写)。
    3. 应用层负责领域实体与DTO的转换:调用仓库前把User实体转成UserDto,从仓库拿到UserDto后再转成User实体供领域逻辑使用。

这个方案的优势是完全隔离了持久层与领域层的依赖,适合对分层隔离要求极高的场景。

方案3:调整仓库接口的定义位置(符合DDD规范)

在标准DDD分层中,仓库接口应该定义在领域层,这是依赖倒置原则的正确应用:领域逻辑需要依赖仓库来获取/持久化实体,所以接口归属于领域层;应用层依赖领域层调用接口;持久层依赖领域层实现接口。

如果你坚持要让应用层作为唯一直接访问领域层的模块,可以调整为:

  1. 在应用层创建Application.DomainContracts子项目,定义实体契约和仓库接口:
    public interface IUserEntity
    {
        int Id { get; }
        string Username { get; }
    }
    
    public interface IUserRepository
    {
        Task<IUserEntity> GetByIdAsync(int id);
    }
    
  2. 领域层引用Application.DomainContracts,让User实体实现IUserEntity接口。
  3. 持久层引用Application.DomainContracts,实现IUserRepository时,内部用自己的数据库实体做映射,再转换为IUserEntity返回给应用层。

这个方案既符合DDD的依赖逻辑,又满足了你「仅应用层直接访问领域层」的要求。


内容的提问来源于stack exchange,提问作者Dodge

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 07:32:57