2

I need to implement such query: In C# Linq2Sql Statements this can be written so:

var query = from f1 in Foo
            from f2 in Foo
            where f1.Id < f2.Id && f1.Value == f2.Value
            select f1;

But I wonder how to do this using C# Expressions. I mean something like this:

var query = Foo.Join(...).Select(...);

I see that Join method gives opportunity only to use equal join f1.Id == f2.Id. But how to write in C# expressions more complex query expressions, where is, for example, such expression as f1.Id < f2.Id?

casperOne
  • 73,706
  • 19
  • 184
  • 253
Dao
  • 2,784
  • 3
  • 28
  • 36

3 Answers3

1

There's no direct conversion since your original query isn't using a join...but I think this might get you close:

var query = Foo.Join(Foo, 
                     f1 => f1.Value, 
                     f2 => f2.Value, 
                     (f1, f2) => new { f1, f2 })
               .Where(g => g.f1.Id < g.f2.Id)
               .Select(g => g.f1);
Justin Niessner
  • 242,243
  • 40
  • 408
  • 536
  • @Justin Niessner: There is a direct conversion, `SelectMany` and anonymous types. – casperOne Jan 19 '11 at 19:45
  • @casperOne - The OP specifically asked how to accomplish his goal using a Join...not other operators. – Justin Niessner Jan 19 '11 at 19:55
  • @Justin Niessner: There is not a specific request for using `Join`, but rather, something "like" a join; the concentration IMO is on "C# Expressions" (which I assume he means is the non-query-syntax version). – casperOne Jan 19 '11 at 19:58
  • @casperOne - Guess it's all in how you interpret the question. All the more reason to be as clear as possible when you post to StackOverflow! – Justin Niessner Jan 19 '11 at 20:00
  • @BothOfYou - Based on the query in the OP, don't you think it's *very likely* that the original structure was a bit misguided? (And should just be rewritten rather than just translated into method syntax?) The original structure suggests that the asker simply may not be very familiar with joins. And as you both know (20k+ rep) a huge portion of SO questions are really just asking the wrong question, no? – shaunmartin Jan 19 '11 at 20:08
  • @shaunmartin: While it's true that `Join` could be used here to give a better semantic meaning overall to the OP's query, I think it would be a worse idea to send the op down the direction of thinking that `Join` could be used for *all* queries like this (which it can't, which is why I specified only "inner join semantics based on equality"). – casperOne Jan 19 '11 at 20:13
1

While other answers will produce the same result, it doesn't translate to the same semantically to the original query syntax.

If you want something semantically closer to the original query syntax, you would use the SelectMany extension method, as that is what query syntax translates to when you have more than one from clause:

var query = Foo.
    // from f1 in Foo
    // from f2 in Foo 
    //
    // Need the anonymous type to carry over the two items
    // in the sequences, the compiler will do the same
    // in your original query, although the names
    // will be much more mangled.
    SelectMany(f => Foo, (f1, f2) => new { f1, f2 }).

    // f1.Id < f2.Id && f1.Value == f2.Value 
    Where(f => f.f1.Id < f.f2.Id && f.f1.Value == f.f2.Value).

    // select f1;
    Select(f => f.f1);

Also, it should be noted that while you can use the Join method, you can only use it in situations where you want inner join semantics based on equality. Anything else and you have to use SelectMany with a call to Where.

Community
  • 1
  • 1
casperOne
  • 73,706
  • 19
  • 184
  • 253
0

If you rearrange your query, you might be able to stick with the expression syntax which is simple and readable. How about joining on the .Value property and filtering on f1.Id < f2.Id? That should provide the results you're looking for.

var query = from f1 in Foo
            join f2 in Foo on f1.Value equals f2.Value
            where f1.Id < f2.Id
            select f1;
shaunmartin
  • 3,849
  • 2
  • 25
  • 26