Unirse / Dónde con LINQ y Lambda


Estoy teniendo problemas con una consulta escrita en LINQ y Lambda. Hasta ahora, estoy recibiendo un montón de errores aquí está mi código:

int id = 1;
var query = database.Posts.Join(database.Post_Metas,
                                post => database.Posts.Where(x => x.ID == id),
                                meta => database.Post_Metas.Where(x => x.Post_ID == id),
                                (post, meta) => new { Post = post, Meta = meta });

Soy nuevo en el uso de LINQ, por lo que no estoy seguro de si esta consulta es correcta.

Author: BartoszKP, 2010-05-04

9 answers

Encuentro que si está familiarizado con la sintaxis SQL, usar la sintaxis de consulta LINQ es mucho más claro, más natural y hace que sea más fácil detectar errores:

var id = 1;
var query =
   from post in database.Posts
   join meta in database.Post_Metas on post.ID equals meta.Post_ID
   where post.ID == id
   select new { Post = post, Meta = meta };

Si realmente estás atascado en el uso de lambdas, sin embargo, su sintaxis es un poco fuera. Aquí está la misma consulta, usando los métodos de extensión LINQ:

var id = 1;
var query = database.Posts    // your starting point - table in the "from" statement
   .Join(database.Post_Metas, // the source table of the inner join
      post => post.ID,        // Select the primary key (the first part of the "on" clause in an sql "join" statement)
      meta => meta.Post_ID,   // Select the foreign key (the second part of the "on" clause)
      (post, meta) => new { Post = post, Meta = meta }) // selection
   .Where(postAndMeta => postAndMeta.Post.ID == id);    // where statement
 750
Author: Daniel Schaffer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-27 15:41:51

Usted podría ir de dos maneras con esto. Usando LINQPad (invaluable si eres nuevo en LINQ) y una base de datos ficticia, construí las siguientes consultas:

Posts.Join(
    Post_metas,
    post => post.Post_id,
    meta => meta.Post_id,
    (post, meta) => new { Post = post, Meta = meta }
)

O

from p in Posts
join pm in Post_metas on p.Post_id equals pm.Post_id
select new { Post = p, Meta = pm }

En este caso particular, creo que la sintaxis de LINQ es más limpia (cambio entre las dos dependiendo de cuál es más fácil de leer).

Lo que me gustaría señalar sin embargo es que si usted tiene claves foráneas apropiadas en su base de datos, (entre post y post_meta) entonces probablemente no necesita una unirse explícitamente a menos que esté tratando de cargar un gran número de registros. Tu ejemplo parece indicar que estás tratando de cargar un solo post y son metadatos. Suponiendo que hay muchos registros post_meta para cada post, entonces usted podría hacer lo siguiente:

var post = Posts.Single(p => p.ID == 1);
var metas = post.Post_metas.ToList();

Si desea evitar el problema n+1, entonces puede decirle explícitamente a LINQ to SQL que cargue todos los elementos relacionados de una sola vez (aunque este puede ser un tema avanzado para cuando esté más familiarizado con L2S). El siguiente ejemplo dice"cuando cargue un Post, también cargue todos sus registros asociados a él a través de la clave foránea representada por la propiedad 'Post_metas'":

var dataLoadOptions = new DataLoadOptions();
dataLoadOptions.LoadWith<Post>(p => p.Post_metas);

var dataContext = new MyDataContext();
dataContext.LoadOptions = dataLoadOptions;

var post = Posts.Single(p => p.ID == 1); // Post_metas loaded automagically

Es posible hacer muchas llamadas LoadWith en un solo conjunto de DataLoadOptions para el mismo tipo, o muchos tipos diferentes. Sin embargo, si haces esto mucho, es posible que solo quieras considerar el almacenamiento en caché.

 58
Author: Damian Powell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-05-04 18:27:28

Sus selectores de teclas son incorrectos. Deben tomar un objeto del tipo de la tabla en cuestión y devolver la clave a usar en la combinación. Creo que te refieres a esto:

var query = database.Posts.Join(database.Post_Metas,
                                post => post.ID,
                                meta => meta.Post_ID,
                                (post, meta) => new { Post = post, Meta = meta });

Puede aplicar la cláusula where después, no como parte del selector de teclas.

 31
Author: Mark Byers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-05-04 18:23:16

Daniel tiene una buena explicación de las relaciones de sintaxis, pero armé este documento para mi equipo con el fin de que sea un poco más fácil de entender para ellos. Espero que esto ayude a alguienintroduzca la descripción de la imagen aquí

 19
Author: Talspaugh27,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-18 12:30:16

Publicando porque cuando empecé LINQ + EntityFramework, observé estos ejemplos durante un día.

Si está utilizando EntityFramework, y tiene una propiedad de navegación llamada Meta en su objeto de modelo Post configurado, esto es muy fácil. Si estás usando entity y no tienes esa propiedad de navegación, ¿qué estás esperando?

database
  .Posts
  .Where(post => post.ID == id)
  .Select(post => new { post, post.Meta });

Si estás haciendo el código primero, configurarías la propiedad de esta manera:

class Post {
  [Key]
  public int ID {get; set}
  public int MetaID { get; set; }
  public virtual Meta Meta {get; set;}
}
 5
Author: Visser,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-09 03:15:23

He hecho algo como esto;

var certificationClass = _db.INDIVIDUALLICENSEs
    .Join(_db.INDLICENSECLAsses,
        IL => IL.LICENSE_CLASS,
        ILC => ILC.NAME,
        (IL, ILC) => new { INDIVIDUALLICENSE = IL, INDLICENSECLAsse = ILC })
    .Where(o => 
        o.INDIVIDUALLICENSE.GLOBALENTITYID == "ABC" &&
        o.INDIVIDUALLICENSE.LICENSE_TYPE == "ABC")
    .Select(t => new
        {
            value = t.PSP_INDLICENSECLAsse.ID,
            name = t.PSP_INDIVIDUALLICENSE.LICENSE_CLASS,                
        })
    .OrderBy(x => x.name);
 3
Author: Mahib,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-09 01:13:43

Podría ser algo como

var myvar = from a in context.MyEntity
            join b in context.MyEntity2 on a.key equals b.key
            select new { prop1 = a.prop1, prop2= b.prop1};
 2
Author: pepitomb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-22 13:25:42

Esta consulta linq debería funcionar para usted. Obtendrá todo el post que tiene meta post.

var query = database.Posts.Join(database.Post_Metas,
                                post => post.postId, // Primary Key
                                meta => meat.postId), // Foreign Key
                                (post, meta) => new { Post = post, Meta = meta });

Consulta SQL equivalente

Select * FROM Posts P
INNER JOIN Post_Metas pm ON pm.postId=p.postId
 0
Author: Ahamed Ishak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-22 18:27:07

1 es igual a 1 dos tablas diferentes unirse

var query = from post in database.Posts
            join meta in database.Post_Metas on 1 equals 1
            where post.ID == id
            select new { Post = post, Meta = meta };
 0
Author: mtngunay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-16 20:41:29