如何将Db类映射到通用存储库中的Entity类?

huangapple go评论92阅读模式
英文:

How to map Db class to Entity class in generic repository?

问题

I created a generic repository class where I implement an interface. I follow clean architecture and located UserDbTbl, BaseRepository, and MappingProfile classes in the Infrastructure project, rest of the classes in Domain and Application projects. What's important here is that I use a db-first approach and it can't be changed.

I retrieved UserDbTbl from the database and want to map it to the entity User in BaseRepository. It wouldn't be a problem if I mapped it in a non-generic, dedicated repository (let's say UserRepository). Then I could easily map fields from UserDbTbl to User. The issue is that I want to make the mapping in the generic repository BaseRepository, which implements general methods applicable to various entities (User, Product, and any others).

I don't know how to map it properly in different BaseRepository methods using AutoMapper. As shown in the example below - let's say that, using the ListAllAsync() method, I would like to extract data from some table using _dbContext.Set<T>().ToListAsync() and then try to map it to the generic entity type <T> - in my code I just map it to IReadOnlyList<T>. Not sure if this is okay at all. I have even more problems with other methods, e.g., DeleteAsync. And the final issue - how to create a mapping profile (class MappingProfile)? I have no idea how I could map it generically. The more that the User class has a navigation property to the Address class.

英文:

I created a generic repository class where I implement an interface. I follow clean architecture and located UserDbTbl, BaseRepository and MappingProfile classes in Infrastructure project, rest of the classes in Domain and Application projects. What's important here is that I use db-first approach and it can't be changed.

I retrieved UserDbTbl from db and want to map it to entity User in BaseRepository. It wouldn't be a problem if I mapped it in non-generic, dedicated repository (let's say UserRepository). Then I could easily map fields from UserDbTbl to Users. The issue is that I want to make mapping in generic repository BaseRepository which implements general methods applicable to various entities (Users, Products and any others).

I don't know how to map it properly in different BaseRepository methods using AutoMapper. As shown in the example below - let's say that, using ListAllAsync() method, I would like to extract data from some table using _dbContext.Set&lt;T&gt;().ToListAsync() and then try to map it to generic entity type &lt;T&gt; - in my code I just map it to IReadOnlyList&lt;T&gt;. Not sure if this is ok at all. I have even more problems with other methods e.g. DeleteAsync. And the final issue - how to create mapping profile (class MappingProfile)? I have no idea how could I map it generically. The more that User class have navigation property to Address class.

  1. // Db Class
  2. public partial class UserDbTbl
  3. {
  4. public int Id { get; set; }
  5. public string UserName { get; set; }
  6. public string Division { get; set; }
  7. public string CreatedBy { get; set; }
  8. public virtual Address Address { get; set; }
  9. }
  10. // Entity class
  11. public class User
  12. {
  13. public int Id { get; set; }
  14. public string UserName { get; set; }
  15. public Address Address { get; set; }
  16. }
  17. // Generic interface
  18. public interface IAsyncRepository&lt;T&gt; where T : class
  19. {
  20. Task&lt;T&gt; GetByIdAsync(int id);
  21. Task&lt;IReadOnlyList&lt;T&gt;&gt; ListAllAsync();
  22. Task&lt;T&gt; AddAsync(T entity);
  23. Task UpdateAsync(T entity);
  24. Task DeleteAsync(T entity);
  25. }
  26. // Interface implementation
  27. public class BaseRepository&lt;T&gt; : IAsyncRepository&lt;T&gt; where T : class
  28. {
  29. protected readonly RegionManagementDbContext _dbContext;
  30. private readonly IMapper _mapper;
  31. public BaseRepository(RegionManagementDbContext dbContext, IMapper mapper)
  32. {
  33. _dbContext = dbContext;
  34. _mapper = mapper;
  35. }
  36. public async Task&lt;IReadOnlyList&lt;T&gt;&gt; ListAllAsync()
  37. {
  38. var dbDataList = await _dbContext.Set&lt;T&gt;().ToListAsync();
  39. var domainMap = _mapper.Map&lt;IReadOnlyList&lt;T&gt;&gt;(dbDataList);
  40. return domainMap;
  41. }
  42. public async Task&lt;T&gt; AddAsync(T entity)
  43. {
  44. var dbDataAdd = await _dbContext.Set&lt;T&gt;().AddAsync(entity);
  45. var domainMap = _mapper.Map&lt;T&gt;(dbDataAdd);
  46. return domainMap;
  47. }
  48. public virtual async Task&lt;T&gt; GetByIdAsync(int id)
  49. {
  50. var dbDataGetId = await _dbContext.Set&lt;T&gt;().FindAsync(id);
  51. var domainMap = _mapper.Map&lt;T&gt;(dbDataGetId);
  52. return domainMap;
  53. }
  54. public async Task DeleteAsync(T entity)
  55. {
  56. var dbDataDelete = _dbContext.Set&lt;T&gt;().Remove(entity);
  57. await _mapper.Map&lt;T&gt;(dbDataDelete);
  58. }
  59. public async Task UpdateAsync(T entity)
  60. {
  61. var dbDataUpdate = _dbContext.Set&lt;T&gt;().Update(entity);
  62. await _mapper.Map&lt;T&gt;(dbDataUpdate);
  63. }
  64. }
  65. // add mapping profile
  66. public class MappingProfile : Profile
  67. {
  68. public MappingProfile()
  69. {
  70. CreateMap&lt;typeof(IAsyncRepository&lt;&gt;), typeof(BaseRepository&lt;&gt;)&gt;();
  71. }
  72. }

答案1

得分: 1

以下是要翻译的代码部分:

  1. public class BaseRepository<TDbEntity, TDomainEntity>
  2. where TDbEntity : class
  3. where TDomainEntity : class
  4. {
  5. public virtual async Task<TDomainEntity> GetByIdAsync(int id)
  6. {
  7. var dbDataGetId = await _dbContext.Set<TDbEntity>().FindAsync(id);
  8. var domainMap = _mapper.Map<TDomainEntity>(dbDataGetId);
  9. return domainMap;
  10. }
  11. }

在映射配置中为每一对实体,如 UserDbTblUser,有这样的部分。

英文:

It might work with having two generic entities for your generic repository, the DB entity and the domain entity.

Something like this:

  1. public class BaseRepository&lt;TDbEntity, TDomainEntity&gt;
  2. where TDbEntity : class
  3. where TDomainEntity : class
  4. {
  5. public virtual async Task&lt;TDomainEntity&gt; GetByIdAsync(int id)
  6. {
  7. var dbDataGetId = await _dbContext.Set&lt;TDbEntity&gt;().FindAsync(id);
  8. var domainMap = _mapper.Map&lt;TDomainEntity&gt;(dbDataGetId);
  9. return domainMap;
  10. }
  11. }

, and then having in the mapping profile configurations for each pair of entities, like UserDbTbl to User.

huangapple
  • 本文由 发表于 2023年3月15日 21:23:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/75745321.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定