2017-05-19 1 views
0

나는 일반 서비스 및 저장소 계층이있는 프로젝트에서 작업하고 있습니다. Automapper를 사용하여 DTO를 엔티티 모델에 매핑합니다. 하나의 엔티티는 하나 이상의 DTO를 가질 수 있습니다. 내 문제는 어떻게 내 일반 저장소 클래스 DTO 서비스 계층에 반환해야 말해야합니까?하나의 엔터티 (Automapper)에 여러 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; } 
} 

DTO들

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); 
} 

창 neric 저장소 구현

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 반환 할 것입니다 어떤 선택합니다. 계약 클래스는 테스트의 일부 였지만 작동하지 않습니다. 서비스의 각 메소드를 원하는 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

이제 "모든 것"을 일반적인 방법으로 만들려고 할 때의 결과에 직면했습니다. 프로그래밍은 모두 컨텍스트에 관한 것입니다. 먼저 모든 것을 분리 한 다음 일반 패턴을 볼 때 일반적인 접근 방식을 적용합니다. – Fabio

+0

답장을 보내 주셔서 감사합니다. @Fabio. 나는 이미 특정 자료를 가지고있는 특정 저장소와 서비스를 가지고있다. 몇 가지 간단한 CRUD 작업을 수행하기 위해 일반적인 것들을 사용하고 싶습니다. 각 저장소에 대해 findBy를 빌드하면 각 엔티티에 대해 동일한 코드를 갖지만 다른 반환 유형 (다른 계약)을 갖게됩니다. 나는 그 상황을 피하고 싶다. 감사! –

+0

당신은 하나의 메소드 'getEntityContract'에서 수행하기를 원한다면 리플렉션없이이 작업을 수행 할 방법이 없을 것이라고 생각합니다. 그러면이 메소드는 매개 변수로 또는 헤더에서 리턴 할 유형에 대해 알아야합니다.), 리플렉션을 사용하여 일반 실행을 사용하여 findBy를 실행합니다. 또한 URL 이름을 변경하십시오. REST와 같이 URL은 "api/entities/byFilter"가 아닌 "api/entity/getEntityByFilter"가되어야합니다. 다른 방법을 찾으면 의견을 말하십시오. – Prince

답변

0

내 대답은 지연되었지만 어쨌든, 여기 있습니다.

이 방법을 찾은 방법은 어떤 엔터티를 반환할지 결정하는 방법이었습니다. 그래서, 내 저장소 내가 저장소를 호출해야, 그래서 지금이

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는 일반적인 유형이 클래스 수준이 아니라 메소드 수준입니다.

다른 사람들에게 도움이되기를 바랍니다. 더 좋은 해결책이 있다면 알려주세요.

건배!

관련 문제