当前位置: 首页 > 知识库问答 >
问题:

将多个DTO添加到单个实体的通用存储库(Automapper)

东门修文
2023-03-14

我在一个项目中工作,我有一个通用的服务和存储库层。我正在使用Automapper将DTO映射到实体模型。一个实体可以有一个或多个DTO。我的问题是,如何告诉我的通用存储库类哪个DTO应该返回到服务层?

实体

[Table("Entity")]
public class Entity
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int id { get; set; }

    [Required]
    public string name { get; set; }

    [Required]
    public string surname { get; set; }
}

DTOs

public class Contract
{
}

[DataContract]
public class EntityContract: Contract
{
    [Required]
    [DataMember]
    public string name { get; set; }

    [Required]
    [DataMember]
    public string surname { get; set; }
}

[DataContract]
public class EntityPassportContract: Contract
{
    [Required]
    [DataMember]
    public string name { get; set; }

    [Required]
    [DataMember]
    public string surname { get; set; }

    [Required]
    [DataMember]
    public string passport { get; set; }
}

通用存储库

public interface IGenericRepository<E, DTO> 
    where E : class
    where DTO: class
{
    List<DTO> findBy(Expression<Func<DTO, bool>> query = null, Func<IQueryable<DTO>, IOrderedQueryable<DTO>> orderBy = null,
                                Expression<Func<DTO, bool>> whereIn = null, int? page = null, int? sizePage = null);
}

通用存储库实现

public abstract class GenericRepository<C, E, DTO> : IGenericRepository<T, DTO> 
    where E : class
    where DTO: class
    where C : IdentityDbContext<User>, new()
{
    //...
    public virtual List<DTO> findBy(Expression<Func<DTO, bool>> query = null, Func<IQueryable<DTO>, IOrderedQueryable<DTO>> orderBy = null,
                                        Expression<Func<DTO, bool>> whereIn = null, int? page = null, int? sizePage = null)
    {
        //...transform DTO queries to E queries and Get IQueriable<E> entity from database
        DTO dtoEntity=entity.ProjectTo<DTO>();
        return dtoEntity;                           
    }
}

通用服务

public interface IService<E, DTO> : IService
    where T: class
    where DTO: class
{
    List<DTO> findBy(Expression<Func<DTO, bool>> query = null, Func<IQueryable<DTO>, IOrderedQueryable<DTO>> orderBy = null,
                                           Expression<Func<DTO, bool>> whereIn = null, int? page = null, int? sizePage = null);
}

通用服务实现

public abstract class Service<E, DTO> : IService<T, DTO>
    where E: class
    where DTO: class
{

    protected IGenericRepository<E, DTO> repository;
    public Service(IGenericRepository<E, DTO> repository,)
    {
        this.repository = repository;
    }
    public virtual List<DTO> findBy(Expression<Func<DTO, bool>> query = null, Func<IQueryable<DTO>, IOrderedQueryable<DTO>> orderBy = null,
                                               Expression<Func<DTO, bool>> whereIn = null, int? page = null, int? sizePage = null)
    {
        return repository.findBy(query, orderBy, whereIn, page, sizePage).ToList();
    }
}

实体存储库和服务

public interface IEntityRepository : IGenericRepository<Entity, Contract>
{
}
public class EntityRepository : GenericRepository<EntitiesDB, Entity, Contract>, IEntityRepository
{
    public EntityRepository(IMapper mapper):base(mapper){ }
}

//Service
public interface IEntityService : IService<Entity, Contract>
{
}
public class EntityService : Service<Entity, Contract>, IEntityService
{
    private IEntityRepository repo;

    public EntityService(IEntityRepository repo) : base(repo)
    {
        this.repo = repo;
    }
}

控制器我想在泛型服务中调用findBy方法,并选择要返回的DTO。合同类是我测试的一部分,但它不起作用。我是否必须使用反射将服务中的每个方法传递给我想要的数据类型?

[RoutePrefix("api/entity")]
public class EntityController : ApiController
{
    public EntityController(IEntityService entityService)
    : base(entityService)
    {
    }
    [Route("getEntityByFilter", Name = "getEntityByFilter")]
    [HttpGet]
    public async Task<IHttpActionResult> getEntityContract(string filter)
    {
        EntityContract entityContract=entityService.findBy(**Parameters**); //Need to call lambda expressions here so i think i need somehow the type.
        return Ok(entityContract);
    }
    [Route("getEntityByFilter2", Name = "getEntityByFilter2")]
    [HttpGet]
    public async Task<IHttpActionResult> getEntityPassportContract(string filter)
    {
        EntityPassportContract entityPassportContract=entityService.findBy(**Parameters**); //Need to call lambda expressions here so i think i need somehow the type.
        return Ok(entityPassportContract);
    }
}

非常感谢提前!我希望这个问题也能帮助其他人!

祝你周末愉快!

卢西亚诺

共有1个答案

姜飞飙
2023-03-14

对不起,我的回答耽搁了,但不管怎样,给你。

我发现这样做的方法是告诉方法我想要返回哪个实体。所以,我的存储库是这样的

public abstract class GenericRepository<C, E> : IGenericRepository<T> 
where E : class
where C : IdentityDbContext<User>, new()
{
    //...
    public virtual List<DTO> findBy<DTO>(Expression<Func<DTO, bool>> query = 
     null, Func<IQueryable<DTO>, IOrderedQueryable<DTO>> orderBy = null,
                                    Expression<Func<DTO, bool>> whereIn = 
      null, int? page = null, int? sizePage = null)
    {
        //...transform DTO queries to E queries and Get IQueriable<E> entity 
           from database
        DTO dtoEntity=entity.ProjectTo<DTO>();
        return dtoEntity;                           
    }
}

所以现在,每次我必须调用存储库时,我都在服务类中这样调用它:

//If I want the EntityListResumeDTO
List<EntityListResumeDTO> EntityListContract = repo.findBy<EntityListResumeDTO>(x=>x.id==1);

//If I want the EntityListCompleteDTO
List<EntityListCompleteDTO> EntityListContract = repo.findBy<EntityListCompleteDTO>(x=>x.id==1);

如您所见,DTO泛型类型不再是类级别的,而是方法级别的。

希望这能帮助其他人,如果你有更好的解决方案,请让我知道。

干杯

 类似资料:
  • 我有几个实体,并使用Spring Data JPA存储库与规范查询我的数据库。因此,我创建了一个泛型类< code>SpecBuilder来基于查询描述(< code>MyQueryDescriptor)构建我的查询。 我的存储库: 和 现在有三件事我不太确定:< br> 1) 使用泛型SpecBuilder是一个干净的设计吗? 2) 有没有办法避免为每个实体编写这些存储库接口?假设一个通用存储库

  • 我的应用程序有250多个表,每个表都有ID和name列。我正在尝试用Hibernate5+将我们的应用程序从Hibernate3迁移到Spring-JPA4.3。 在当前的hibernate层中,我有(选项1): 因此,如何在一个JPA存储库中执行以下操作:

  • 我有两件事情要做:在鼠标悬停时突出显示JPanel,在鼠标拖动时移动一个蓝色方块。问题是,这需要我将MouseListeners添加到不同的组件中。当我这样做时,我只能使用一个功能——另一个被阻止了。我该怎么做才能让两个功能都工作? 注意:有时候JFrame不会显示任何东西——你只需要一直运行它,直到它显示为止(通常需要2-3次尝试)。如果它做了任何其他奇怪的事情,就继续运行它,直到它工作。如果之

  • 我试图创建一个简单的网站,其中托管主题和评论。我已经从主题开始,并为它们创建了存储库: 我已经在servlet上下文中定义了存储库的路径。xml: 现在,我想在我的存储库中包含注释,但以下代码不起作用: 我的项目甚至都没建好。你能给我一个建议吗,如何为多个实体创建存储库(主题类和注释类是用@Entity声明的)? 我面对的是: TopicRepository类图标上有HDD图片 org.sprin

  • 这里的 Spring 文档 http://docs.spring.io/spring-data/data-jpa/docs/current/reference/html/repositories.html#repositories.custom-implementations 提供了将自定义功能添加到所有存储库或单个存储库的示例,而不是同时添加到两者。 假设我想向所有存储库添加一些自定义函数(使用

  • 问题内容: 是否可以使用Spring Data Rest为同一JPA实体发布两个不同的存储库?我给两个存储库提供了不同的路径和rel-name,但是这两个存储库中只有一个可以用作REST端点。我拥有两个存储库的要点是,其中一个是摘录,仅显示实体的基本字段。 问题答案: 可怕的部分不仅是你只能有1个弹簧数据仓库休息(@RepositoryRestResource)每实体,但也说,如果你有一个普通JP