-1

I have this Linq C# query in my code:

   var res = from i in context.Instrument
        join g in context.FtpServerGroup on i.FtpServerGroupId equals g.Id
        join f in context.FtpServer on g.Id equals f.FtpServerGroupId
        where i.Deleted && f.NetAddress == netaddress
       select i;

I need to translate it to another syntax (LINQ extension methods), used by .NET core, here an example not related to the previous query:

context.Instrument.Where(w => !w.Deleted).Include(x => x.FtpServerGroup).ThenInclude(x => x.FtpServers).FirstAsync(i => i.Id == id);

My question is, I couldn't find a way to convert the first query (a triple join) into the other syntax. Any advice on how to find some documentation or how to do it?

Gianluca Ghettini
  • 11,129
  • 19
  • 93
  • 159
  • A simple trick is often to look at your generated exe with [IlSpy](http://ilspy.net/), disabling everything in View->Options->Decompiler – xanatos Mar 10 '17 at 10:01
  • Note that some things are much easier to do in LINQ "syntax" than in functional syntax. – xanatos Mar 10 '17 at 10:03
  • 1
    Joins in a LINQ query means that some relations are missing. Why join in the query instead of adding an `Instrupent.Group` property? You could simply load the required instruments with `where i.Group.Server.NetAddress=x` – Panagiotis Kanavos Mar 10 '17 at 10:05
  • LINQ isn't a replacement for SQL. It makes warking with ORM's simpler though. If you have to perform 3 joins, it would be easier to just write the appropriate SQL statement – Panagiotis Kanavos Mar 10 '17 at 10:07
  • 1
    I'm with @PanagiotisKanavos It's much better to use **navigation properties** than plain joins. Also, `Include` / `ThenInclude` pattern **can** be used with query syntax (or mixed query syntax), so the question makes no sense. – Ivan Stoev Mar 10 '17 at 10:24
  • 1
    Wait, you already have these properties? Why don't you `.Include()` them then? Remove the joins and just write `from in in context.Instrument.Include(x => x.FtpServerGroup).ThenInclude(x => x.FtpServers)` – Panagiotis Kanavos Mar 10 '17 at 10:36

2 Answers2

2

With power of resharper:

var res =context.Instrument.Join(context.FtpServerGroup, i => i.FtpServerGroupId, g => g.Id, (i, g) => new {i, g})
                .Join(context.FtpServer, @t => g.Id, f => f.FtpServerGroupId, (@t, f) => new {@t, f})
                .Where(@t => i.Deleted && f.NetAddress == netaddress)
                .Select(@t => i);
Backs
  • 24,430
  • 5
  • 58
  • 85
  • 1
    If you check the second snippet, the classes already have the appropriate navigation properties and the joins simply aren't needed. The OP could have used the query syntax, or a `.Where(@i => i.Deleted && i.FtpServerGroup.FtpServer.NetAddress == netaddress)` – Panagiotis Kanavos Mar 10 '17 at 10:39
  • @PanagiotisKanavos well, I can agree with you, but question is not about logic, it's just about syntax. So, I made simple transform :) – Backs Mar 10 '17 at 10:48
  • 1
    That's the point. No joins are needed at all because the navigation properties are already there – Panagiotis Kanavos Mar 10 '17 at 10:56
2

Jon Skeet has a nice cheat sheet (scroll down) for translating query syntax into method syntax.

Your query translates to:

var res = context.Instrument.Join(context.FtpServerGroup, i => i.FtpServerGroupId, g => g.Id, (i,g) => new {i,g})
                 .Join(context.FtpServer, x => x.g.Id, f => f.FtpServerGroupId, (f, x) => new {f, x.g, x.i})
                 .Where(x => x.i.Deleted && x.f.NetAddress == netaddress)
                 .Select(x => x.i);
René Vogt
  • 43,056
  • 14
  • 77
  • 99