You could go two ways with this. Using LINQPad (invaluable if you're new to LINQ) and a dummy database, I built the following queries:
Posts.Join(
Post_metas,
post => post.Post_id,
meta => meta.Post_id,
(post, meta) => new { Post = post, Meta = meta }
)
or
from p in Posts
join pm in Post_metas on p.Post_id equals pm.Post_id
select new { Post = p, Meta = pm }
In this particular case, I think the LINQ syntax is cleaner (I change between the two depending upon which is easiest to read).
The thing I'd like to point out though is that if you have appropriate foreign keys in your database, (between post and post_meta) then you probably don't need an explicit join unless you're trying to load a large number of records. Your example seems to indicate that you are trying to load a single post and it's meta data. Assuming that there are many post_meta records for each post, then you could do the following:
var post = Posts.Single(p => p.ID == 1);
var metas = post.Post_metas.ToList();
If you want to avoid the n+1 problem, then you can explicitly tell LINQ to SQL to load all of the related items in one go (although this may be an advanced topic for when you're more familiar with L2S). The example below says "when you load a Post, also load all of its records associated with it via the foreign key represented by the 'Post_metas' property":
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
It is possible to make many LoadWith
calls on a single set of DataLoadOptions
for the same type, or many different types. If you do this lots though, you might just want to consider caching.