【问题标题】:C# n-layer entity changes not reflected in DTO after insert插入后 C# n 层实体更改未反映在 DTO 中
【发布时间】:2017-08-30 10:19:32
【问题描述】:

抱歉标题,我找不到合适的描述。

我有四层:

  • 核心层:包含 DTO、服务接口和存储库。
  • 业务层:包含处理业务逻辑的“服务”。
  • 数据访问层:包含处理数据库访问和实体到 DTO 转换的存储库。
  • 表示层:UI 的东西

我遇到了一个我不知道如何最好地解决的问题。我正在向数据库异步添加一个实体,如下所示:

// The AdministrationRate has an ID property, Entity Framework does treat the property as an Identity and does increment it.
var adminRate = new AdministrationRate() {FosterChildID = fosterChild.ID};
await adminRateService.AddAdministrationRate(adminRate);

AdministrationRateService:

public async Task AddAdministrationRate(AdministrationRate administrationRate) => await repo.AddAdministrationRate(administrationRate);

AdministrationRateRepository:

 //I use a generic repository to avoid code repition.
 //Notice the DTO to entity conversion. ID is not set in the conversion.
 public async Task AddAdministrationRate(AdministrationRate administrationRate) => await Add(administrationRate.ToEntity());

存储库:

public async Task Add(TEntity entity)
{
    using (var db = new DatabaseContext())
    {
        db.Entry(entity).State = EntityState.Added;
        await db.SaveChangesAsync();
    }
}

确实有效,但问题是添加后新生成的实体 id 并未反映在 DTO 中(DTO.ID = 0)。

我不可能返回更新后的实体,因为它需要我将实体转换为我的表示层中的 DTO 以使其始终保持异步。

由于通用存储库,我也不能只返回 ID。

我真的不想摆脱通用存储库,因为它非常有用,但我真的看不到另一种在不更改数据库的情况下安全地执行此操作的方法(我做不到)。

那么,我该怎么办?

【问题讨论】:

    标签: c# entity-framework asynchronous n-layer


    【解决方案1】:

    这里有几个我会尝试的想法。不确定它们中的任何一个是否适合您的需求,但可能会让您开始(或至少开始讨论:)):

    1;为您的 DTO 引入一个接口,例如 IDto。然后您可以更改通用存储库以返回 Task<IDto> 而不是 Task。在Add 方法中将实体转换为具体的Dto,通过IDto 引用返回,然后在服务中将其转换回。

    2;如果您有像IRepository<TEntity>Repository<TEntity> 这样的通用存储库,那么您可以尝试将另一个参数引入通用存储库并将其设为IRepository<TEntity,TDto>。这样,您可以保持架构的通用性,但也可以从 Add 方法返回 Task<Dto>

    3;你可以更进一步:创建一个IDto<TEntity> 接口。然后你可以有一个User 实体和一个UserDto:IDto<User>。然后您可以将Add 方法的返回类型更改为Task<IDto<TEntity>>。或者,再次使用双参数存储库IRepository<TEntity,TDto>,并添加约束,以便TDto 必须实现IDto<TEntity>

    【讨论】:

      【解决方案2】:

      答案: 我为这个问题找到了两种解决方案,后者是我实际使用的解决方案。


      解决方案 1:

      我发现我可以让 Add 方法返回实体的 ID,方法是将通用存储库的 Add 方法标记为虚拟,然后在特定存储库之一中覆盖它,最后从调用代码中捕获结果。这当然意味着更多的代码,但我也不会在错误的层中从实体转换为 DTO(这不是一个选项)。


      解决方案 2:

      显然await 关键字异步返回任务的结果类型,而不是像result 那样阻塞它,所以我能够从我的存储库转换并返回一个 DTO:

      AdministrationRateRepository:

      public async Task<AdministrationRate> AddAdministrationRate(AdministrationRate administrationRate) => (await Add(administrationRate.ToEntity())).ToModel();
      

      如果有人可以评论我是否需要使我的 ToEntity()ToModel() 方法异步,以及如何做到这一点。

      编辑:哦,没有注意到有人发帖。我会看看你的建议 Akos,谢谢。

      【讨论】:

        猜你喜欢
        • 2011-11-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-31
        • 1970-01-01
        • 2014-08-03
        • 2022-06-11
        • 1970-01-01
        相关资源
        最近更新 更多