J'ai des problèmes avec une requête écrite en LINQ et Lambda. Jusqu'à présent, je reçois beaucoup d'erreurs, voici mon code:
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 });
LINQ est nouveau pour moi, je ne suis donc pas sûr que cette requête soit correcte.
Je trouve que si vous connaissez la syntaxe SQL, l’utilisation de la syntaxe de requête LINQ est beaucoup plus claire, plus naturelle et facilite la détection des erreurs:
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 vous êtes vraiment bloqué sur l'utilisation de lambdas, votre syntaxe est un peu décalée. Voici la même requête, en utilisant les méthodes d'extension 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
Vous pourriez aller de deux manières avec cela. En utilisant LINQPad (inestimable si vous débutez dans LINQ) et une base de données fictive, j'ai construit les requêtes suivantes:
Posts.Join(
Post_metas,
post => post.Post_id,
meta => meta.Post_id,
(post, meta) => new { Post = post, Meta = meta }
)
ou
from p in Posts
join pm in Post_metas on p.Post_id equals pm.Post_id
select new { Post = p, Meta = pm }
Dans ce cas particulier, je pense que la syntaxe LINQ est plus propre (je change entre les deux en fonction de ce qui est le plus facile à lire).
Ce que j'aimerais toutefois souligner, c'est que si vous avez la clé étrangère appropriée dans votre base de données (entre post et post_meta), vous n'avez probablement pas besoin d'une jointure explicite sauf si vous essayez de charger un grand nombre d'enregistrements. . Votre exemple semble indiquer que vous essayez de charger un seul message et ses métadonnées. En supposant qu'il existe de nombreux enregistrements post_meta pour chaque message, vous pouvez alors effectuer les opérations suivantes:
var post = Posts.Single(p => p.ID == 1);
var metas = post.Post_metas.ToList();
Si vous souhaitez éviter le problème n + 1, vous pouvez explicitement indiquer à LINQ to SQL de charger tous les éléments associés en une fois (même s’il s’agit peut-être d’une rubrique avancée lorsque vous êtes plus familiarisé avec L2S). L'exemple ci-dessous indique "lorsque vous chargez une publication, chargez également tous les enregistrements qui lui sont associés via la clé étrangère représentée par la propriété '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
Il est possible d'effectuer de nombreux appels LoadWith
sur un seul ensemble de DataLoadOptions
pour le même type, ou de nombreux types différents. Si vous faites cela souvent, vous voudrez peut-être simplement envisager la mise en cache.
Vos sélecteurs de clé sont incorrects. Ils doivent prendre un objet du type de la table en question et renvoyer la clé à utiliser dans la jointure. Je pense que vous voulez dire ceci:
var query = database.Posts.Join(database.Post_Metas,
post => post.ID,
meta => meta.Post_ID,
(post, meta) => new { Post = post, Meta = meta });
Vous pouvez appliquer la clause where par la suite, pas dans le cadre du sélecteur de clé.
Publier parce que quand j'ai commencé LINQ + EntityFramework, j'ai observé ces exemples pendant un jour.
Si vous utilisez EntityFramework et que vous avez une propriété de navigation nommée Meta
dans la configuration de votre objet modèle Post
, la tâche est extrêmement simple. Si vous utilisez entity et n'avez pas cette propriété de navigation, qu'attendez-vous?
database
.Posts
.Where(post => post.ID == id)
.Select(post => new { post, post.Meta });
Si vous commencez par écrire du code, vous devez configurer la propriété comme suit:
class Post {
[Key]
public int ID {get; set}
public int MetaID { get; set; }
public virtual Meta Meta {get; set;}
}
J'ai fait quelque chose comme ça;
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);
Cela pourrait être quelque chose comme
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};
Cette requête linq devrait fonctionner pour vous. Il aura tous les messages qui ont post meta.
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 });
Requête SQL équivalente
Select * FROM Posts P
INNER JOIN Post_Metas pm ON pm.postId=p.postId
1 est égal à 1 deux jointures de table différentes
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 };