2010-05-04 180 views
266

Tengo problemas con una consulta escrita en Linq y Lambda. Hasta el momento, estoy recibiendo una gran cantidad de errores que aquí está mi código:C# Joins/Donde con Linq y Lambda

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, así que no estoy seguro de si esta consulta es correcta.

+6

lo que estás tratando de lograr? – GerManson

+2

¿Qué quieres que haga la consulta en una oración? – hunter

+4

Sus selectores de teclas son * forma * demasiado complicados. Si desea seleccionar por id, solo x => x.ID está bien. –

Respuesta

616

Me parece que si usted está familiarizado con la sintaxis SQL, usando la sintaxis de consulta LINQ es mucho más claro, más natural, y hace que sea más fácil de 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 usted está realmente atascado en sin embargo, usando lambdas, tu sintaxis está un poco desajustada. Aquí está la misma consulta, utilizando 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 
+4

@Emanuele Greco, con respecto a su edición, "La igualdad en los campos ID se establece en la condición UNIRSE, ¡no necesita usar la cláusula WHERE!": La cláusula WHERE no prueba la igualdad entre campos ID, está probando la igualdad entre la publicación Columna ID y el parámetro id declarado fuera de la consulta. –

+2

Impresionante pieza de 'lambda' y es fácil de usar y comprender – ppumkin

+0

Gracias, linq query clear. –

24

Sus selectores de teclas son incorrectos. Deben tomar un objeto del tipo de la tabla en cuestión y devolver la clave para usar en la combinación. Creo que quiere decir 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.

48

Podrías ir de dos maneras con esto. Usando LINQPad (muy útil si usted es nuevo en LINQ) y una base de datos ficticia, he construido 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 limpio (Cambio entre los dos dependiendo de cuál es más fácil de leer).

Lo que me gustaría señalar es que si tienes claves externas apropiadas en tu base de datos (entre post y post_meta) entonces probablemente no necesites una unión explícita a menos que intentes cargar una gran cantidad de registros Su ejemplo parece indicar que está intentando cargar una sola publicación y sus metadatos. Suponiendo que hay muchos registros post_meta para cada puesto, entonces usted podría hacer lo siguiente:

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

Si se quiere evitar el n + 1 problema, entonces se puede decir de manera explícita LINQ a SQL para cargar todos los relacionados artículos de una vez (aunque este puede ser un tema avanzado para cuando esté más familiarizado con L2S). El ejemplo de abajo dice "cuando se carga un Post, también cargar todos sus registros asociados a ella a través de la clave externa 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 LoadWith llamadas en una conjunto único de DataLoadOptions para el mismo tipo, o muchos tipos diferentes. Sin embargo, si haces esto mucho, tal vez quieras considerar el almacenamiento en caché.

+0

*** LinqPad *** y ** CRM 2016 **? – Kiquenet

2

Podría ser algo así 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}; 
5

Publicación porque cuando empecé LINQ + ADO.NET Entity Framework, me quedé mirando estos ejemplos para un día.

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

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

Si estás haciendo el código en primer lugar, que le establecer la propiedad de esta manera:

class Post { 
    [Key] 
    public int ID {get; set} 
    public int MetaID { get; set; } 
    public virtual Meta Meta {get; set;} 
} 
8

Daniel tiene una buena explicación de las relaciones sintácticas, pero poner este documento en conjunto para mi equipo para que sea un poco más simple de entender. Espero que esto ayude a alguien enter image description here

1

Esta consulta linq debería funcionar para usted. Obtendrá toda la publicación que tiene meta de publicación.

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 }); 

Equivalente de consultas SQL

Select * FROM Posts P 
INNER JOIN Post_Metas pm ON pm.postId=p.postId 
1

que 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); 
0

1 es igual a 1 dos tablas diferentes se unen

 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 };