2010-10-14 14 views
5

Dadas dos clases en su archivo .dbml LINQ to SQL con las siguientes propiedades.encapsulando la lógica en una consulta de linq a sql a través del método de extensión

Customer 
    CustomerId 
    FirstName 
    LastName 
    AddressId 

Address 
    AddressId 
    Street 
    City 
    State 
    Zip 

Puede construir una consulta LINQ como la siguiente.

using(var db = new MyDataContext()) 
{ 
    results = db.Customers 
     .Where(c => c.LastName.BeginsWith("o")) 
     .Select(c => new 
      { 
       c.CustomerId, 
       MailingAddress = c.FirstName + " " 
        + c.LastName 
        + Environment.NewLine 
        + c.Address.Street 
        + Environment.NewLine 
        + c.Address.City + ", " 
        + c.Address.State + " " 
        + c.Address.Zip 
      }).ToList(); 

} 

Ahora digamos que quería excapsular la lógica para armar la dirección postal. Dos formas de lograr eso serían agregar una nueva propiedad a la clase Cliente o crear un método de extensión.

public static class CustomerExtensions 
{ 
    public static string GetMailingAddress(this Customer cust) 
    { 
     return cust.FirstName + " " 
        + cust.LastName 
        + Environment.NewLine 
        + cust.Address.Street 
        + Environment.NewLine 
        + cust.Address.City + ", " 
        + cust.Address.State + " " 
        + cust.Address.Zip; 
    } 
} 

public partial class Customer 
{ 
    public string MailingAddress 
    { 
     get 
     { 
      return this.FirstName + " " 
        + this.LastName 
        + Environment.NewLine 
        + this.Address.Street 
        + Environment.NewLine 
        + this.Address.City + ", " 
        + this.Address.State + " " 
        + this.Address.Zip; 
     } 
    } 
} 

ahora se podían usar uno de esos y se podrían obtener los resultados correctos

using(var db = new MyDataContext()) 
{ 
    results = db.Customers 
     .Where(c => c.LastName.BeginsWith("o")) 
     .Select(c => new 
      { 
       c.CustomerId, 
       c.MailingAddress, //new property 
       Address2 = c.GetMailingAddress() // new extension method 
      }).ToList(); 

} 

El problema con estas dos formas es que al hacerlo provocará que haya un ida y vuelta innecesaria a la base de datos para cada fila que recupera. La consulta inicial extraerá la información de la tabla Cliente, y luego tendrá que graduar cada registro de dirección individualmente cuando evalúe la dirección postal.

¿Hay alguna manera de encapsular esta lógica y vincularla a la clase de los clientes de tal forma que no necesite ningún viaje adicional de ida y vuelta a la base de datos?

Creo que debe haber alguna manera de crear un método de extensión que en su lugar devuelva una expresión en lugar de una cadena. ¿Estoy en lo cierto? Si es así, ¿cómo haría esto?

Respuesta

3

Sé que esto no es exactamente lo que está buscando, pero se puede hacer esto:

var options = new DataLoadOptions(); 
options.LoadWith<Customer>(c => c.Address); 
db.LoadOptions = options; 

Entonces sólo hará un viaje que la dirección se recupera con el cliente.

+0

Gracias Richard, eso funciona, pero tienes razón, no es exactamente lo que espero encontrar por dos razones. Primero, el método de llamada necesita saber algo sobre lo que está involucrado en la construcción de 'MailingAddress', es decir, que requiere la tabla de direcciones. En segundo lugar, digamos que la tabla de direcciones en realidad contenía muchos más de 5 campos, creo que hacer esto generaría muchos más datos de los que realmente necesitamos. – eoldre

Cuestiones relacionadas