Utiliza un repositorio para enumerar una raíz agregada. A menudo, sus controladores trabajan con una raíz agregada, que puede filtrar, ordenar, etc., según lo requiera el usuario.
Por lo tanto, utilizo un repositorio en la línea de lo que ya se ha mencionado.
Sin embargo, a veces tengo que trabajar dentro de especificaciones más complejas, donde usar una raíz agregada y/o un montón de repositorios es doloroso, ineficiente o simplemente imposible. Por ejemplo, es posible que deba ejecutar un informe comercial grande, o tal vez ejecutar un comando por lotes.
En este tipo de casos, también he definido ICommand
/IQuery
, con una aplicación de base de NH cuidar el material de fontanería (como genérico Repository
hace).
Lo que hago es hacer una interfaz que represente el contrato de la especificación, exponiendo a los miembros que pueda necesitar para ayudarme a construir los parámetros necesarios. Luego realizo una implementación de esa especificación, usando NH como columna vertebral, cumpliendo con la especificación usando la técnica más adecuada (una declaración HQL, SQL sin procesar, Criteria, QueryOver ... lo que sea).
Aquí hay una tosca ilustración de lo que quiero decir. Tenga en cuenta que utilizo un ICommandProvider
arbitrario, que es un objeto que crea nuevas instancias de un comando según sea necesario (en caso de que necesite emitir varios comandos en una operación). Registraría mis comandos con un IoC y haré que el proveedor trabaje con él para crear instancias de comando.
public interface ICommand
{
}
public interface ICommandProvider
{
TCommand Create<TCommand>()
where TCommand : ICommand;
}
public interface IQuery<TResult> : ICommand
{
TResult Execute();
}
public class NhCommand : ICommand
{
// plumbing stuff here, like finding the current session
}
public class DelinquentAccountViewModel
{
public string AccountName { get; set; }
public decimal Amount { get; set; }
}
public interface IDelinquentAccountsQuery : IQuery<IEnumerable<DelinquentAccountViewModel>>
{
void AmountGreaterThan(decimal amount);
// you could define members for specifying sorting, etc. here
}
public class DelinquentAccountsQuery : NhCommand
{
public IEnumerable<DelinquentAccountViewModel> Execute()
{
// build HQL and execute results, resulting in a list of DelinquentAccountViewModels
// using _amountGreaterThan as a parameter
return null;
}
private Decimal _amountGreaterThan;
public void AmountGreaterThan(Decimal amount)
{
_amountGreaterThan = amount;
}
}
Uso de un controlador podría ser algo como esto:
public class DelinquentAccountsController : Controller
{
protected ICommandProvider CommandProvider { get; private set; }
public DelinquentAccountsController(ICommandProvider commandProvider)
{
CommandProvider = commandProvider;
}
public ActionResult Index(decimal amount)
{
var query = CommandProvider.Create<IDelinquentAccountsQuery>();
query.AmountGreaterThan(amount);
return View(query.Execute());
}
}
Nada dice que no puede hacer todo de su acceso a los datos mediante un comando/consulta, pero es más trabajo de lo que necesito. Encuentro que el enfoque de repositorio estándar (usando LINQ contra NHibernate) maneja aproximadamente el 95% del acceso a datos que requieren mis aplicaciones.
Gracias Bronumski , Creo que tomaré un enfoque combinado: métodos bien definidos llamados por los servicios web y una interfaz IQueryable adicional para manejar consultas genéricas desde la interfaz web. – mbue