2017-05-19 116 views
0

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

实体

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

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

周末愉快!

Luciano

+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通用类型不再是课堂级别,而是在方法级别。

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

干杯!

相关问题