11

No estoy muy familiarizado con el patrón MVC. ¿Podría decirme cuál de las siguientes tres acciones de controlador es mejor? Gracias :)¿Es una buena práctica tener consulta de linq en Controladores?

(1) Tener consulta en acción:

public ActionResult List() 
{ 
    var query = repository.Query().Where(it => it.IsHandled).OrderBy(it => it.Id); 
    // ... 
} 

(2) Tener consulta en el servicio:

public ActionResult List() 
{ 
    var items = service.GetHandledItemsOrderById(); 
    // ... 
} 

(3) tiene orden por la acción :

public ActionResult List() 
{ 
    var items = service.GetHandledItems().OrderBy(it => it.Id); 
    // ... 
} 

Si elegimos (1), entonces tenemos demasiada lógica comercial en el controlador?

Si elegimos (2), puede haber muchos métodos de servicio como GetXXXByYYY().

Si elegimos (3), por la que encapsulamos Where(it => it.IsHandled) pero no
OrderBy(it => it.Id.

¿Alguna idea?

Respuesta

3

Depende. :)

Mi opinión:

me gusta mantener mi servicio suelto, para minimizar el código duplicado. También soy fanático de las tuberías y los filtros.

Esto es lo que haría (y lo hago).

Servicio

public ICollection<Item> GetHandledItems<TKey>(OrderingOptions<Item, TKey> orderingOptions) 
{ 
    return repository 
     .Query() 
     .WhereHandled() 
     .WithOrdering(orderingOptions) 
     .ToList();  
} 

ItemFilters.cs

public static IQueryable<Item> WhereHandled(this IQueryable<Item> source) 
{ 
    return source.Where(it => it.IsHandled); 
} 

public static IOrderedQueryable<T> WithOrdering<T, TKey>(
    this IQueryable<T> source, 
    OrderingOptions<T, TKey> orderingOptions) 
{ 
    return orderingOptions.SortDescending 
     ? source.OrderByDescending(orderingOptions.OrderingKey) :              
     source.OrderBy(orderingOptions.OrderingKey); 
} 

OrderingOptions.cs

public class OrderingOptions<T,TKey> 
{ 
    public OrderingOptions(Expression<Func<T,TKey>> orderingKey, bool sortDescending = false) 
    { 
     OrderingKey = orderingKey; 
     SortDescending = sortDescending; 
    } 

    public Expression<Func<T,TKey>> OrderingKey { get; private set; } 
    public bool SortDescending { get; private set; } 
} 

esta manera, yo u puede especificar el orden en el controlador:

var items = service.GetHandledItems(new OrderingOptions(it => it.Id)); 

Las diferencias entre el arriba y opciones 3:

  • encima materializa secuencia antes de volver al controlador. La opción 3 no lo hace, lo cual es peligroso (podría terminar devolviendo la consulta a Ver y romper el patrón MVC).
  • POCO genérico "Pedido", se puede usar en cualquier lugar y guarda sus consultas D-R-Y.
  • El servicio se convierte en tonto, y simplemente un mitigator entre el repositorio y el controlador (que es todo lo que debe hacer, IMO). Lógica (por ejemplo, filtros) abstraída a un lugar.

HTH

+0

Gracias. Bu si "GetHandledItems()" devuelve una colección (no IQueryable), no podemos realizar proyecciones en la consulta. Afectará el rendimiento. –

+0

@Dylan: haga sus proyecciones en el servicio antes de ejecutar la consulta, ya sea en línea o mediante otro método de conexión, por ejemplo: 'return repo.Query(). WhereHandled(). WithOrdering(). AsSomeProjectedType()' – RPM1984

+0

También vea esta ** brillante ** vid RobCon en MVC Pipes & Filters: http://www.asp.net/mvc/videos/aspnet-mvc-storefront-part-3-pipes-and-filters – RPM1984

4

Estoy seguro de que las opiniones pueden variar, pero he aprendido a tratar de mantener la mayor lógica comercial en el servicio que pueda. 3 sería mi elección. Con 1, ya has detectado el problema. Con 2, está introduciendo prioridad de visualización en un servicio. Con 3, maneja las preferencias de visualización donde sea necesario. Si tuviera que introducir otra interfaz en su capa empresarial, necesita iteraciones de código potencialmente innecesarias al elegir 2.

+0

La página debe mostrar los elementos que se manejan por Id fin. ¿Por qué "visualizar elementos ya procesados ​​(procesados)" es lógica de negocios y debe estar en servicio, mientras que "mostrar elementos ordenados por id" es preferencia de visualización? –

+0

Creo que "mostrar elementos manejados" y "mostrar los elementos ordenados por id" son ambas preferencias de visualización? Entonces, ¿deberíamos elegir 1? –

+1

Creo que mi pregunta debería ser: (1) ¿Es "dónde (it => it.IsHandled)" lógica de negocios? (2) ¿Es la lógica de negocios "OrderBy (it => it.Id)"? –

Cuestiones relacionadas