Pregunta

Estas preguntas no me permiten dormir, ya que desde un año estoy tratando de encontrar una solución, pero ... todavía no pasó nada en mi mente. Probablemente puedas ayudarme, porque creo que este es un problema muy común.

Tengo una aplicación N capaz: capa de presentación, capa lógica de negocios, capa de modelo. Supongamos por simplicidad que mi aplicación contiene, en la capa de presentación, un formulario que permite a un usuario buscar a un cliente. Ahora el usuario llena los filtros a través de la interfaz de usuario y hace clic en un botón. Algo sucede y la solicitud llega a la capa de presentación a un método como CustomerSearch(CustomerFilter myFilter). Esta capa lógica de negocios ahora lo mantiene simple: crea una consulta en el modelo y recupera los resultados.

Ahora la pregunta: ¿Cómo se enfrenta el problema de cargar datos? Me refiero a que la capa de lógica comercial no sabe que ese método en particular se invocará solo por esa forma. Por lo tanto, creo que no sabe si el formulario solicitante necesita solo los objetos del cliente o los objetos del cliente con las entidades de pedido vinculado.

Intento explicar mejor: nuestro formulario solo quiere enumerar a los clientes que buscan por apellido. No tiene nada que ver con las órdenes. Entonces, la consulta de la lógica de negocios será algo así como:

(from c in ctx.CustomerSet
where c.Name.Contains(strQry) select c).ToList();

Ahora esto funciona correctamente. Dos días después, su jefe le pide que agregue un formulario que le permita buscar clientes como el otro y debe mostrar el recuento total de pedidos creados por cada cliente. Ahora me gustaría reutilizar esa consulta y agregar el pedazo de lógica que se adjunte (incluir) Orden y recupere eso.

¿Cómo enfrentarías esta solicitud?

Aquí está la mejor idea (creo) que tuve desde ahora. Me gustaría saber de usted: mi método de investigación de clientes en BLL no crea la consulta directamente, sino que pasa a través de métodos de extensión privados que componen la ObjectQuery como:

private ObjectQuery<Customer> SearchCustomers(this ObjectQuery<Customer> qry, CustomerFilter myFilter)

y

private ObjectQuery<Customer> IncludeOrders(this ObjectQuery<Customer> qry)

Pero esto no me convence, ya que parece demasiado complejo.

Gracias Marco

¿Fue útil?

Solución

Considere mudarse a DTO para la interfaz entre la capa de presentación y la capa de negocios, ver por ejemplo:- http://msdn.microsoft.com/en-us/magazine/ee236638.aspx

Algo como Automapper puede aliviar gran parte del dolor asociado con mudarse a los DTO y el movimiento hará explícito lo que puede y no puede hacer con los resultados de una consulta, es decir, si está en el DTO, está cargado, si no es necesario que necesite un DTO diferente. .

Su plan actual suena un poco más bien acoplado entre la capa de presentación y la capa de datos.

Otros consejos

Estoy de acuerdo con el comentario de Hightechrider en referencia al uso de DTO, sin embargo, tiene una pregunta válida con respecto a las entidades comerciales.

Una posible solución (estoy usando algo en esta línea en un proyecto que estoy desarrollando) es usar DTO que son de solo lectura (al menos desde la perspectiva de la capa de presentación. Sus operaciones de consulta/GET solo devolverían DTO, esto lo haría. Déle la capacidad de carga perezosa.

Puede configurar su capa comercial para devolver un objeto editable que envuelva el DTO cuando se actualiza/crea un objeto/entidad. Su objeto editable podría hacer cumplir cualquier regla comercial y luego, cuando se guardó/pasó a la capa comercial, la DTO envolvió (con los valores actualizados) podría pasar a la capa de datos.

public class Editable
{
    //.......initialize this, other properties/methods....

    public bool CanEdit<TRet>(Expression<Func<Dto, TRet>> property)
    {
        //do something to determine can edit
        return true;
    }

    public bool Update<TRet>(Expression<Func<Dto, TRet>> property, TRet updatedValue)
    {
        if (CanEdit(property))
        {
            //set the value on the property of the DTO (somehow)
            return true;
        }
        return false;
    }

    public Dto ValueOf { get; private set;}
}

Esto le brinda la capacidad de aplicar si el usuario puede obtener objetos editables de la capa comercial, así como permitir que el objeto comercial aplique si el usuario tiene permiso para editar propiedades específicas de un objeto. Un problema común con el que me encuentro con el dominio en el que trabajo es que algunos usuarios pueden editar todas las propiedades y otros no pueden, mientras que cualquiera puede ver los valores de las propiedades. Además, la capa de presentación gana la capacidad de determinar qué exponer como editable para el usuario según lo dictado y aplicado por la capa de negocios.

Otro pensamiento que tenía es que su capa comercial no exponga a IQueryable o tome expresiones estándar como argumentos que transmite a su capa de datos. Por ejemplo, tengo una consulta de construcción de página algo como esto:

public class PageData
{
    public int PageNum;
    public int TotalNumberPages;
    public IEnumerable<Dto> DataSet;
}

public class BL
{
    public PageData GetPagedData(int pageNum, int itemsPerPage, Expression<Func<Dto, bool>> whereClause)
    {
        var dataCt = dataContext.Dtos.Where(whereClause).Count();
        var dataSet = dataContext.Dtos.Where(whereClause).Skip(pageNum * itemsPerPage).Take(itemsPerPage);

        var ret = new PageData
                        { 
                          //init this
                        };

        return ret;
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top