2012-03-31 10 views
7

Tengo un código como el siguiente:¿Cómo definir mi propia construcción LINQ en C#?

class PacketDAO{ 
    //... 
    public void UpdatePacketStatus(Guid packetID, Status status) 
    { 
     using (var ctx = new DataContext()) 
     { 
      var packet = ctx.Packet.SingleOrDefault(p => p.PacketID == packetID); 
      packet.Status = status; 
      ctx.SubmitChanges(); 
     } 
    } 

    public void UpdatePacketTime(Guid packetID, DateTime? time) 
    { 
     using (var ctx = new DataContext()) 
     { 
      var packet = ctx.Packet.SingleOrDefault(p => p.PacketID == packetID); 
      packet.Time = time; 
      ctx.SubmitChanges(); 
     } 
    } 
    //... 
}  

Nos puede notar un poco aburrida repetición en el código.

Por lo tanto, sería bueno escribir un método de actualización genérica de una manera que nos podemos permitir nosotros mismos para escribir algo como esto:

packet.Update<Guid, Packet>(guid, p => p.Time = DateTime.Now); 
packet.Update<Guid, Packet>(guid, p => p.Status = Status.Ok); 

Dime, por favor, ¿es posible escribir un procedimiento de este tipo?

¿De qué libro puedo aprender eso?

(he encontrado sólo un ejemplo cercano: http://msdn.microsoft.com/en-us/library/cc981895.aspx, pero no es lo suficientemente claro cómo derivar mi método de actualización de eso)

Gracias.

UPD.

Ok, Jon Skeet dice que hay algo mal en la pregunta, y estoy de acuerdo, que mis llamadas deben tener un aspecto diferente, creo que estas llamadas son posibles:

packet.Update<Packet>(p => p.packetID == guid, p => p.Time = DateTime.Now); 
packet.Update<Packet>(p => p.packetID == guid, p => p.Status = Status.Ok); 
+0

Tener un método tipo LINQ que actualice los datos es un poco antinatural – zerkms

+1

Un libro que recomendaría es [Pro Linq] (http://www.amazon.com/Pro-LINQ-Language-Integrated-Experts/ dp/1590597893). –

Respuesta

10

Vamos a empezar escribiendo una función auxiliar ordinaria. Esto no tiene nada que ver con LINQ.

public static void UpdatePacket(Guid packetID, Action<Packet> update) 
{ 
    using (var ctx = new DataContext()) 
    { 
     var packet = ctx.Packet.SingleOrDefault(p => p.PacketID == packetID); 
     update(packet); 
     ctx.SubmitChanges(); 
    } 
} 

Como puede ver, se puede utilizar la actualización delegado para extraer la única pieza pequeña de código que es diferente para cada llamada. El resto es lo mismo, y ahora lo tenemos centralizado y reusabe.

También puede hacer que el método genérico:

public static void UpdatePacket<TEntity>(Expression<Func<TEntity, bool>> filter, Action<TEntity> update) 
{ 
    using (var ctx = new DataContext()) 
    { 
     var e = ctx.GetTable<TEntity>().Single(filter); 
     update(e); 
     ctx.SubmitChanges(); 
    } 
} 

Si usted quiere tener el filtro automatizado, es necesario utilizar la API de Expresión y reflexión para construir la expresión de filtro. El código para eso es un poco más largo.

+4

Tenga en cuenta que ni siquiera estamos utilizando un método de extensión. No es necesario aquí. Vaya simple cuando lo simple es suficiente. – usr

+2

En lugar de escribir comentarios para su propia respuesta, puede agregar la información adicional directamente a la respuesta editándola :) –

+0

Sí, pero si necesitamos un método de actualización para un solo campo de una tabla diferente de Packet, obtendremos el repetición de código en una capa de abstracción algo más alta, ya que escribimos casi la misma función de ayuda con una firma decir static estático UpdateMessage (int messageId, Action actualización). – gentlenub

Cuestiones relacionadas