插入后C#n层实体更改未在DTO中反映

时间:2017-08-30 10:19:33

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

对标题感到抱歉,我无法找到合适的说明。

我有四层:

  • 核心层:包含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。

我真的不想摆脱通用存储库,因为它非常有用,但我无法在不改变数据库的情况下安全地看到另一种方法(我可以' t)。

那么,我该怎么办?

2 个答案:

答案 0 :(得分:0)

以下是我尝试过的一些想法。不确定它们是否适合您的需求,但可能会让您开始(或至少开始讨论:)):

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

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

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

答案 1 :(得分:0)

<强>答案: 我找到了两个解决这个问题的方法,后者是我实际上要解决的问题。

解决方案1:

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

解决方案2:

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

AdministrationRateRepository:

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

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

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