linq to sql - tutorial - Entidad LINQ a SQL y clases de contexto de datos: encapsulación de objeto de negocio
linq c# tutorial español (8)
¿Cuáles son sus formas favoritas de encapsular LINQ en clases de entidad SQL y clases de contexto de datos en objetos comerciales?
¿Qué has encontrado para trabajar en una situación dada?
¿Has inventado o llevado a patrones específicos?
Consulte el código fuente de la aplicación MVC Sample que Rob Conery está creando:
http://www.codeplex.com/mvcsamples/
Él tiene una capa de entidad separada que mapea a las clases de LINQ a SQL.
En este momento estoy tratando de usar las clases de entidad LINQ a SQL como objetos de negocios, para pasarlos entre funciones y servicios.
Por supuesto, debe tener clases de entidad separadas para el acceso a la base de datos , por lo que el diseño de su base de datos puede cambiar sin cambiar los objetos comerciales.
¡Estaría muy interesado en una buena solución para esto también!
Hice algunos experimentos utilizando Entity Framework y Linq to Entities como una forma de separar aún más mi código de cliente de la base de datos, pero me pareció difícil de usar y estaba preocupado por el rendimiento.
En mi proyecto actual utilizo Linq to SQL como mi capa de datos, pero tengo clases separadas donde implemento todas las consultas de Linq. Las clases devuelven entidades definidas en mi contexto de Linq a SQL, pero las consultas están ocultas en los métodos.
Estoy jugando con la idea de tener una capa separada de modelo OO (mejor soporte para prácticas OO), pero eso usa LINQ to SQL bajo el capó. La idea es tener un archivo xml que una herramienta personalizada usará para generar el código. Como las entidades de LINQ to SQL son demasiado complicadas para mis preferencias, generaré automáticamente nuevas clases para usar como mis entidades y, por supuesto, DataContext estará completamente oculto para el código del cliente. La respuesta corta es: Crear nuevas clases de entidad pero usar las entidades subyacentes LINQ to SQL y DataContext.
Los artículos de Ian Cooper en CodeBetter.com y Stephen Walther me resultaron invaluables al comprender la necesidad de escribir primero las entidades POCO y luego asignarlas a la base de datos en lugar de hacerlo al revés (que es lo que solía hacer siempre) )
Tiendo a usar el patrón Repositorio para encapsular DataContexts.
Me gustaría encontrar una mejor manera de emitir objetos POCO desde mi capa de datos mientras uso LINQ2SQL.
Acabo de publicar una muestra de cómo puede estructurar su aplicación que utiliza Linq a Sql para el almacenamiento, usando plantillas IoC y T4.
http://daniel.wertheim.se/2010/03/14/linq-to-sql-how-to-separate-the-entities-and-the-datacontext/
Encontré un patrón que creo que funciona mejor: en mi caso, al menos.
Extiendo clases de entidad usando clases parciales. Utilizo clases parciales para que la firma de la entidad no cambie (vea la llamada DeleteOnSubmit
en el método Delete
).
He cocinado un pequeño ejemplo. Aquí hay una imagen de la base de datos y la configuración de la clase LINQ a SQL:
Y aquí está la clase parcial en la que implemento lógica de negocios:
/// <summary>
/// This class extends BusinessLogicDataContext.Products entity class
/// </summary>
public partial class Product
{
/// <summary>
/// New up a product by column: dbo.Products.ProductId in database
/// </summary>
public Product(Int32 id)
{
var dc = new BusinessLogicDataContext();
// query database for the product
var query = (
from p in dc.Products
where p.ProductId == id
select p
).FirstOrDefault();
// if database-entry does not exist in database, exit
if (query == null) return;
/* if product exists, populate self (this._ProductId and
this._ProductName are both auto-generated private
variables of the entity class which corresponds to the
auto-generated public properties: ProductId and ProductName) */
this._ProductId = query.ProductId;
this._ProductName = query.ProductName;
}
/// <summary>
/// Delete product
/// </summary>
public void Delete()
{
// if self is not poulated, exit
if (this._ProductId == 0) return;
var dc = new BusinessLogicDataContext();
// delete entry in database
dc.Products.DeleteOnSubmit(this);
dc.SubmitChanges();
// reset self (you could implement IDisposable here)
this._ProductId = 0;
this._ProductName = "";
}
}
Usando la lógica de negocios implementada:
// new up a product
var p = new Product(1); // p.ProductId: 1, p.ProductName: "A car"
// delete the product
p.Delete(); // p.ProductId: 0, p.ProductName: ""
Además: las clases de entidad LINQ a SQL son de naturaleza muy abierta. Esto significa que la propiedad correspondiente a la columna dbo.Products.ProductId implementa tanto un getter como un setter; este campo no debe ser modificable.
Que yo sepa, no puede anular propiedades usando clases parciales, entonces lo que generalmente hago es implementar un administrador que reduce el objeto usando una interfaz:
public interface IProduct
{
Int32 ProductId { get; }
void Delete();
}