asp.net - Prácticas recomendadas para aplicaciones web de LINQ a SQL
linq-to-sql n-tier (2)
En mi experiencia en la creación de aplicaciones web, siempre utilicé un enfoque de n niveles. Un DAL que obtiene datos del DB y rellena los objetos, y BLL que obtiene objetos del DAL y realiza cualquier lógica de negocios requerida en ellos, y el sitio web que obtiene sus datos de visualización del BLL. Recientemente comencé a aprender LINQ, y la mayoría de los ejemplos muestran las consultas que ocurren directamente desde el código subyacente de la aplicación web (es posible que solo haya visto ejemplos demasiado simplificados). En las arquitecturas de n niveles, esto siempre se vio como un gran no-no.
No estoy seguro de cómo diseñar una nueva aplicación web. He estado usando Server Explorer y el diseñador de dbml en VS2008 para crear las relaciones de objeto y dbml. Me parece un poco incierto si el dbml se consideraría la capa DAL, si el sitio web llamara a los métodos dentro de un BLL, que luego haría las consultas LINQ, etc.
¿Cuáles son algunas de las mejores prácticas de arquitectura general o enfoques para crear una solución de aplicación web utilizando LINQ to SQL?
El LINQ to SQL es el acceso DB en la implementación DAL, si desea separar entre DAL y BLL. Si tiene una Aplicación Web menos compleja (y tampoco tiene la intención de cambiar los back-ends de DB), puede alejarse sin DAL / BLL explícito y hacer todo lo que esté en el código. LINQ to SQL funciona muy bien para operaciones de solo lectura, pero se siente un poco más trabajo para implementar operaciones de escritura.
Me temo que de hecho has visto ejemplos demasiado simplificados. LINQ to SQL (System.Data.Linq) es su capa DAL. Las clases que genera L2S son su dominio (pero no para confundir con el Diseño Dirigido por Dominio ). Además de eso, aún puede escribir su Business Layer.
Siempre trato de evitar filtrar el LINQ a SQL DataContext
en la capa de presentación (su aplicación web). Por lo tanto, no debería ser capaz de crear o confirmar un DataContext
. Tampoco debe devolver objetos IQueryable<T>
a la capa de presentación. IMO, la capa empresarial debe tener control total sobre la vida útil del DataContext
(unidad de trabajo) y la forma de las consultas SQL.
Sin embargo, hay varios sabores. Algunas personas carpa para relajar estas limitaciones. Otros incluso van mucho más allá. Depende de tu propio gusto y del tamaño de la aplicación. Mientras más grande sea la aplicación, más se justifica agregar capas de abstracción.
Al no permitir que IQueryable
s y otras cosas relacionadas con datos abandonen la capa de negocio, terminarás teniendo algunos desafíos interesantes. Por ejemplo, la capa de presentación debe indicar a la capa empresarial cómo ordenar los resultados. Si bien podría dejar que la capa de presentación ordene los resultados, esto significaría que tendría que obtener todos los datos de la base de datos y la página en la capa de presentación, lo que daría lugar a un sistema con muy mal rendimiento. Hay varias soluciones a este problema. En todos los casos, deberá informar a la capa empresarial cómo ordenar los resultados por usted. Las soluciones se pueden encontrar aquí en SO cuando busca el tipo dinámico LINQ . He escrito una solución de este tipo , aquí .
Otro desafío que no permite que IQueryable
s deje su BL es que los objetos de dominio a menudo no pueden salir de su BL. La mayoría de sus objetos de dominio LINQ a SQL contendrán propiedades cargadas perezosas (por ejemplo, colecciones a otros objetos de dominio). Sin embargo, cuando DataContext
tiene el control de Business Layer, se eliminará antes de devolver los resultados a la capa de presentación. Cuando la presentación no accede a una propiedad con carga diferida, se producirá una excepción porque ya se ha eliminado el DataContext
. Cuando desecha el DataContext
en su capa de negocio, este comportamiento es, por supuesto, "por diseño". Permitir que la capa de presentación obtenga propiedades cargadas perezosas significa que el BL pierde el control sobre las consultas que se envían a la base de datos, perdiendo así el control del rendimiento.
Para resolver este problema, debe devolver objetos de transferencia de datos (DTO) del BL a la capa de presentación. Un DTO contendrá solo datos y ningún DataContext
interno, y ninguna propiedad de carga lenta. Un DTO puede formatearse especialmente para la solicitud real en cuestión. Los DTO, por supuesto, conducen a la sobrecarga de codificación ellos mismos, por lo que el tamaño de su sistema y las necesidades de rendimiento deben justificarlo. Para hacerlo más fácil, tiendo a poner métodos de proyección estáticos en un DTO. Si bien esto no se ajusta al principio de separación de preocupaciones , creo que es una solución muy práctica. Busque por ejemplo en este CustomerDTO:
public class CustomerDTO
{
public int CustomerId { get; set; }
public string Name { get; set; }
// City is flatterned from Address.City.
public string City { get; set; }
internal static IQueryable<CustomerDTO> AsDTO(IQueryable<Customer> customers)
{
return
from customer in customers
select new CustomerDTO()
{
CustomerId = customer.Id,
Name = customer.Name,
City = customer.Address.City
};
}
}
Este DTO define un método AsDTO
interno, que puede convertir una colección de objetos de dominio del Customer
en una colección de DTO CustomerDTO
. Esto hace que la conversión de objetos de dominio a DTO sea mucho más fácil. Busque por ejemplo en este método BL:
public static CustomerDTO[] GetCustomersByCountry(string country)
{
using (var db = ContextFactory.CreateContext())
{
IQueryable<Customer> customers =
(from customer in db.Customers
where customer.Address.Country == country
orderby customer.Name, customer.Id);
return CustomerDTO.AsDTO(customers).ToArray();
}
}
Lo bueno de este enfoque es que cuando observas la consulta SQL, verás que solo se recuperarán de la base de datos el identificador del cliente, el nombre y la tabla Ciudad de la dirección. Esto se debe a que el método AsDTO
traduce una IQueryable
a otra, permitiendo que LINQ to SQL realice la operación total en la base de datos.
Espero que esto te dé algunas ideas de lo que puedes hacer. Por supuesto, esta es mi opinión sobre el tema y las cosas que he encontrado prácticas en mi situación.