Asked  7 Months ago    Answers:  5   Viewed   31 times

I'm having trouble with a query written in LINQ and Lambda. So far, I'm getting a lot of errors here's my 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 });

I'm new to using LINQ, so I'm not sure if this query is correct.

 Answers

49

I find that if you're familiar with SQL syntax, using the LINQ query syntax is much clearer, more natural, and makes it easier to spot errors:

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

If you're really stuck on using lambdas though, your syntax is quite a bit off. Here's the same query, using the LINQ extension methods:

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
Tuesday, June 1, 2021
 
Joegramming
answered 7 Months ago
24

For joins, I strongly prefer query-syntax for all the details that are happily hidden (not the least of which are the transparent identifiers involved with the intermediate projections along the way that are apparent in the dot-syntax equivalent). However, you asked regarding Lambdas which I think you have everything you need - you just need to put it all together.

var categorizedProducts = product
    .Join(productcategory, p => p.Id, pc => pc.ProdId, (p, pc) => new { p, pc })
    .Join(category, ppc => ppc.pc.CatId, c => c.Id, (ppc, c) => new { ppc, c })
    .Select(m => new { 
        ProdId = m.ppc.p.Id, // or m.ppc.pc.ProdId
        CatId = m.c.CatId
        // other assignments
    });

If you need to, you can save the join into a local variable and reuse it later, however lacking other details to the contrary, I see no reason to introduce the local variable.

Also, you could throw the Select into the last lambda of the second Join (again, provided there are no other operations that depend on the join results) which would give:

var categorizedProducts = product
    .Join(productcategory, p => p.Id, pc => pc.ProdId, (p, pc) => new { p, pc })
    .Join(category, ppc => ppc.pc.CatId, c => c.Id, (ppc, c) => new {
        ProdId = ppc.p.Id, // or ppc.pc.ProdId
        CatId = c.CatId
        // other assignments
    });

...and making a last attempt to sell you on query syntax, this would look like this:

var categorizedProducts =
    from p in product
    join pc in productcategory on p.Id equals pc.ProdId
    join c in category on pc.CatId equals c.Id
    select new {
        ProdId = p.Id, // or pc.ProdId
        CatId = c.CatId
        // other assignments
    };

Your hands may be tied on whether query-syntax is available. I know some shops have such mandates - often based on the notion that query-syntax is somewhat more limited than dot-syntax. There are other reasons, like "why should I learn a second syntax if I can do everything and more in dot-syntax?" As this last part shows - there are details that query-syntax hides that can make it well worth embracing with the improvement to readability it brings: all those intermediate projections and identifiers you have to cook-up are happily not front-and-center-stage in the query-syntax version - they are background fluff. Off my soap-box now - anyhow, thanks for the question. :)

Saturday, June 5, 2021
 
mschuett
answered 6 Months ago
68

Without the using directive, methods like .Where, .Select, will not resolve. That means that LINQ the language part will not work. You would have to code it long-hand (and backwards!):

List<int> _NewList = System.Linq.Enumerable.ToList(
    System.Linq.Enumerable.Where(_Numbers, _Number => _Number % 2 == 0)
);

Note that this becomes increasing complex for longer examples with groups, orders, "let"s, joins etc. Unless you are doing something fairly simple, it would be advisable to just find a way to add the using directive.

Note, however, that if _Numbers is a List<T>, you can just use (for this single example):

List<int> _NewList = _Numbers.FindAll(_Number => _Number % 2 == 0);
Friday, July 30, 2021
 
TomPuts
answered 4 Months ago
27

Linq is language integrated query. When using linq, a small anonymous function is often used as a parameter. That small anonymous function is a lambda expression.

var q = someList.Where(a => a > 7);

In the above query a => a > 7 is a lambda expression. It's the equivalent of writing a small utility method and passing that to Where:

bool smallMethod(int value)
{
  return value > 7;
}

// Inside another function:
var q = someList.Where(smallMethod);

This means that your question is really not possible to answer. Linq and lambdas are not interchangeable, rather lambdas are one of the technologies used to implement linq.

Thursday, August 5, 2021
 
eliotlencelot
answered 4 Months ago
91

The custom extension Ivan posted in the comment to my question solved the problem. It removes the instruction to join if the condition in the ternary operator evaluates to false.

Sunday, November 21, 2021
 
Jeremy
answered 1 Week ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share