-1

我正在使用现有数据库实现干净的架构,使用脚手架命令我已经在基础设施层中生成了 POCO 实体,并在域层中手动创建了实体以便稍后映射它们。

在应用层,我有带有一些标准操作的通用接口存储库。

public interface IRepository<T> where T : class
 {
     Task<IReadOnlyList<T>> GetAllAsync();
     Task<T> GetByIdAsync(int id);
     Task<T> AddAsync(T entity);
     Task UpdateAsync(T entity);
     Task DeleteAsync(T entity);
 }

根据 Clean-Architecture 的原则,我在 Infrastructure 层中实现它。

public class Repository<T> : IRepository<T> where T : class
    {

        protected readonly MyDBContext _MyDBContext;
        public Repository( MyDBContext mydbContext)
        {
            _MyDBContext= mydbContext;
        }
        public async Task<T> AddAsync(T entity)
        {
            await _MyDBContext.Set<T>().AddAsync(entity);
            await _MyDBContext.SaveChangesAsync();
            return entity;
        }

-----
----

我正在使用带有 CQRS 的调解器模式,当我尝试从 API 层保存用户时,我最终会遇到以下异常。

System.InvalidOperationException: Cannot create a DbSet for 'ABC.Domain.Entities.User' because this type is not included in the model for the context. However, the model contains an entity type with the same name in a different namespace: 'ABC.Infrastructure.Models.User'.

如果我能够将域实体映射到上述存储库实现中的基础设施实体,它将得到解决。

在上述实现中,T是 ABC.Domain.Entities.User,而不是 ABC.Infrastructure.Models.User。

由于规则清理架构所有依赖项都向内流动,核心不依赖于任何其他层。

请帮助我将传入的域实体与上述存储库实现中的基础设施实体进行映射,以便我也可以将这些通用方法用于其他实体操作。

检查我的骨架回购

https://gitlab.com/mail2mdilyas/workcontinent/-/blob/master/Work.Continent.Infrastructure/Repositories/Base/Repository.cs

在上述类中,“AddAsync”操作在通用存储库(Repository.cs)中,以后可以用于不同域实体的不同插入操作。在这里我不会知道什么是 T :

公共类存储库:IRepository where T:类

请告诉我查找传入域实体并将其映射到数据实体的通用方法。

4

1 回答 1

0

我会说你有两种不同的方法来处理这个问题。您可以将域模型映射到表结构,并让基础设施层上的配置文件为您进行映射。这就是我现在更喜欢这样做的方式,并且可以轻松调整您的代码库。因此,对于您的实体配置modelBuilder.Entity<Professional>-Professional类应该是来自您的域而不是基础设施的配置。如果您再次查看他的样本,Ardalis 也在使用这种方法。

作为替代方案,您可以使基础架构层上的存储库实现了解两种不同的模型,并在存储库本身的实现中进行映射。您必须将两种不同的泛型类型传递给Repository<TDomainEntity, TDbModel>并在 DI 注册期间正确声明它。但是,存储库接口本身必须接受域实体,因为您不应该将数据库模型泄漏到基础架构层之外。

public class Repository<TDomainEntity, TDbModel>
    : IRepository<TDomainEntity>
    where TDomainEntity : class
    where TDbModel : class
{
    protected readonly MyDBContext _dbContext;
    protected readonly IMapper _mapper;
    
    public Repository(MyDBContext dbContext, IMapper mapper)
    {
        _dbContext= dbContext;
        _mapper = mapper;
    }
        
    public async Task<TDomainEntity> AddAsync(TDomainEntity entity)
    {
        TDbModel model = _mapper.Map<TDbModel>(entity);
        await _dbContext.Set<TDbModel>().AddAsync(model);
        await _dbContext.SaveChangesAsync();
        return entity;
    }
}

我会说这样做有很多缺点。您有一个不必要的映射层,因为您可以通过模型配置操作域实体到数据库表的映射。如果您的模型中出现任何新要求,这也会增加您必须进行的更改的数量。您还必须使用一些反射魔法来根据命名约定或其他东西匹配您的域实体和数据库模型,或者手动进行大量注册。

于 2022-01-27T10:15:43.147 回答