2011-10-21 6 views
11

Tengo una consulta tirando de una base de datos:¿Cómo puedo establecer propiedades en todos los elementos de una consulta linq con valores de otro objeto que también se extrae de una consulta?

List<myClass> items = new List<myClass>(from i in context 
         select new myClass 
         { 
          A = i.A, 
          B = "", // i doesn't know this, this comes from elsewhere 
          C = i.C 
         } 

También tengo otra consulta que hace una cosa similar:

List<myClass2> otherItems = new List<myClass2>(from j in context 
          select new myClass2 
          { 
           A = j.A, // A is the intersection, there will only be 1 A here but many A's in items 
           B = j.B 
          } 

En realidad, estas clases son mucho más grandes y consulta de datos que se separa no sólo por base de datos pero también por servidor. ¿Es posible utilizar una consulta LINQ para rellenar la propiedad B para todos los items donde los artículos.A se cruzan? Todos los predicados integrados de LINQ aparecen solo para hacer agregados, selecciones o expresiones bool.

En mi cerebro que tenían algo como esto, pero esto es todo lo que fuera:

items.Where(x => x.B = (otherItems.Where(z => z.A == x.A).Single().B)); 

O estoy siendo ridícula con tratar de hacer este trabajo en LINQ y sólo debería abandonarlo a favor de un bucle donde el ajuste real se vuelve trivial? Debido a los plazos, recurriré al bucle for (y de todos modos es probable que termine siendo mucho más legible a largo plazo), pero ¿es posible hacer esto? ¿Sería necesario un método de extensión para agregar un predicado especial para permitir esto?

+0

Yo diría que su ciclo for es una buena implementación. – JonH

+0

¿Podría mostrar un conjunto de datos simple que tiene la estructura principal que está buscando? ¿Qué está tratando de lograr esa última consulta? – Tormod

+0

@Tormod: la segunda consulta contiene la variable 'B'. Estoy buscando un predicado o método de extensión que realice la población de la variable 'B' en la primera colección. –

Respuesta

21

LINQ está diseñado para consultando. Si intentas establecer cosas, definitivamente deberías usar un bucle (probablemente foreach). Eso no significa que no podrá usar LINQ como parte de ese bucle, pero no debería tratar de aplicar un efecto secundario dentro de LINQ.

+0

Una contradicción podría ser el uso de inserciones, actualizaciones y eliminaciones. Esto sugiere que podría estar diseñado para algo más que solo consultas. Puedo aceptar que los predicados predeterminados que vienen empaquetados dentro del marco son específicos de las consultas solamente, pero me hace preguntar si la aplicación de un método de extensión exhaustivo se puede extender más allá de las consultas simples. Reconozco completamente la diferencia entre "puedo" y "debería". En este punto, estoy explorando la posibilidad (y tratando de llenar vacíos en mi propio conocimiento de LINQ). –

+0

@JoelEtherton: Son parte de las adiciones para proveedores específicos de LINQ, no son parte de LINQ. Cada proveedor LINQ es "la parte de consulta que sigue el patrón LINQ" más otras partes que son específicas del proveedor. –

+0

Creo que algo así encajaría en LINQ to Objects, pero puedo entender por qué no es una implementación predeterminada. Entonces, en su opinión, si tuviera una necesidad de algo como esto que justificara el costo del esfuerzo, sería necesario (¿es prudente?) Implementar mi propio proveedor personalizado de LINQ to MyNamespace? –

0

Primero consulta los otros artículos. Haga un ToDictionary() en el resultado. Luego, cuando consulte la base de datos, haga esto:

var items = from i in context 
    select new myClass 
    { A = i.A, 
    B = otherItems[i.A], 
    C = i.C 
    } 
+0

LINQ no permite la combinación de consultas de datos y consultas en memoria. Se compilará pero generará una excepción de tiempo de ejecución porque las secuencias locales no se pueden usar en contextos de datos.Para que funcione la parte de consulta de datos, tendría que ejecutar eso y llevarlo a una secuencia local y luego realizar esta otra selección que crearía una consulta redundante (algo que usaría LINQ para evitar). –

+0

Derecha. El cierre local no se traducirá a través del árbol de expresiones en el proveedor LINQ Query. Bueno, depende de cómo quiera que se ejecute la consulta. Si desea que la consulta se evalúe de forma diferida, corre el riesgo de golpearla muchas veces al iterar. Pero supongo que podría hacerlo con src.Select (remdata => new {}). AsEnumerable(). Select (localdata => new {A = ld.a, B = otherItems [ld.a], C = ld .do}) – Tormod

Cuestiones relacionadas