Según mi comprensión de CQRS, crearía un conjunto de DTO que cumplen los requisitos de las pantallas de la interfaz de usuario o las aplicaciones que pueden necesitar consumirlas.
El hecho de que exista en el proyecto se basa en los requisitos, ya que dependería de exponer estos DTO a través de servicios web. En cuyo caso yo no lo pondría en la Capa Web, sino en la capa de Aplicación o en una capa de Fachada dedicada.
Luego, tendría un repositorio de solo lectura o una capa de acceso a datos que llene los DTO directamente. Creo que el lado de Query debe optimizarse para el rendimiento de lectura, en cuyo caso las consultas directas/procedimientos almacenados en vistas o tablas de base de datos y SqlDataReaders harían el mejor trabajo aquí. Pero definitivamente valdría la pena abstraer este acceso detrás de una interfaz para que pueda agregar una implementación en caché más adelante en la pista.
Si está utilizando un ORM y desea asignar sus Entidades de Dominio a los DTO, entonces podría tener un QueryRepository genérico que tenga métodos que tomen una especificación IS o una construcción similar para definir sus consultas, luego un objeto DtoAssembler para crear la Dtos de tus objetos de Dominio. Luego tenga una implementación con un objeto de primera clase para cada una de las consultas que va a realizar.
Aquí está un ejemplo bastante artificial, pero espero que te da una idea.
public interface ISpecification<T>
{
Expression<Func<T, bool>> Predicate { get; }
}
public class ActiveCustomersSpecification : ISpecification<Customer>
{
private Expression<Func<Customer, bool>> predicate;
public ActiveCustomersSpecification()
{
predicate = c => c.IsActive;
}
#region ISpecicfication<Customer> Members
public Expression<Func<Customer, bool>> Predicate
{
get { return predicate; }
}
#endregion
}
public interface IQueryRepository<T>
{
IQueryable<T> GetQuery(ISpecification<T> specification);
IEnumerable<T> FindAllBy(ISpecification<T> specification);
}
public class CustomerDtoAssembler
{
public CustomerDto AssembleFrom(Customer customer)
{
var customerDto = new CustomerDto
{
Id = customer.Id
};
return customerDto;
}
}
Acabo de encontrar una publicación de blog de Jak Charlton que describe por qué decidió no usar DDD para consultar en absoluto: "El lado de la consulta de CQS no necesita entidades fuertemente tipadas, ni requiere DTO fuertemente tipadas - dado que se trata en gran medida de datos ad-hoc que mantienen estas entidades y los DTO consumirían una cantidad desproporcionada de tiempo de desarrollo para algo que un DataTable pueda manejar más que adecuadamente " http://devlicio.us/blogs/casey/archive/2009/ 06/22/we-are-not-doing-ddd-part-two-cqs.aspx – rohancragg