С этим можно пойти двумя путями. Используя LINQPad (неоценимо, если вы новичок в LINQ) и фиктивную базу данных, я построил следующие запросы:
Posts.Join(
Post_metas,
post => post.Post_id,
meta => meta.Post_id,
(post, meta) => new { Post = post, Meta = meta }
)
или
from p in Posts
join pm in Post_metas on p.Post_id equals pm.Post_id
select new { Post = p, Meta = pm }
В данном конкретном случае я думаю, что синтаксис LINQ более чистый (я переключаюсь между двумя в зависимости от того, какой из них легче читать).
Я хотел бы отметить, что если у вас есть подходящие внешние ключи в вашей базе данных (между post и post_meta), то вам, вероятно, не понадобится явное соединение, если вы не пытаетесь загрузить большой количество записей. Ваш пример указывает на то, что вы пытаетесь загрузить один пост и его метаданные. Предполагая, что для каждого сообщения имеется много записей post_meta, вы можете сделать следующее:
var post = Posts.Single(p => p.ID == 1);
var metas = post.Post_metas.ToList();
Если вы хотите избежать проблемы n + 1, то вы можете явно указать LINQ to SQL, чтобы загружать все связанные элементы за один раз (хотя это может быть сложной темой, когда вы более знакомы с L2S) , В приведенном ниже примере говорится, что «когда вы загружаете сообщение, также загружайте все связанные с ним записи через внешний ключ, представленный свойством 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
Можно сделать много вызовов LoadWith
для одного набора DataLoadOptions
для одного и того же типа или для множества различных типов. Если вы делаете это много, вы, возможно, просто захотите рассмотреть кеширование.