ef9999
ef9999

Reputation: 41

C# Linq query flattening multi-level classes

I have a class structure as follows below (there can be any number of each subclass and there can also be multiple Masters). I want use a linq query to get a flattened list of Subfolios, filtered by the “Index ” property of Subfolio.

I think I can get the Subfolios by Master using either:

IEnumerable< Subfolio> result = from dd in devices.Master
                     where dd.ID == 14
                     from pfo in dd. Portfolio
                     from folio in pfo.Folio
                     from subfolio in folio.Subfolio
                     where subfolio.Ind == 32
                     select subfolio;

Or

IEnumerable<Subfolio> result =
            devices.master.Where(x => x.ID == 14)
                .SelectMany(y => y.PFO) 
                .SelectMany(z => z.Folio)
                .SelectMany(a => a.Subfolio)
                .Where(b=>b.Ind==32);

I could do the same for each slave and combine the results with the Master query, but is there a way of doing this in one linq operation. At the moment I am using a large nest of foreach loops, which is very clunky.

The simplified Class structure is:

Devices
  Master
    Portfolio
      Folio
         Subfolio
         Subfolio
      Folio
         Subfolio
         Subfolio
         Subfolio   
    Portfolio
      Folio
         Subfolio
         Subfolio
      Folio
         Subfolio
         Subfolio
         Subfolio
  Slave
     Portfolio
       Folio
         Subfolio
         Subfolio
       Folio
         Subfolio
         Subfolio
         Subfolio   
     Portfolio
       Folio
         Subfolio
         Subfolio
       Folio
         Subfolio
         Subfolio
         Subfolio
  Slave
     Portfolio
       Folio
         Subfolio
         Subfolio
       Folio
         Subfolio
         Subfolio
         Subfolio   
      Portfolio
       Folio
         Subfolio
         Subfolio
       Folio
         Subfolio
         Subfolio
         Subfolio

Upvotes: 0

Views: 1134

Answers (2)

ef9999
ef9999

Reputation: 41

Further to above, this is my full solution (I didn't make it clear that Slaves are a subclass of Masters)

 public nF GetValuebyuNidIndex(dev devices, UInt32 MuNID, ushort nFIndex)
    {
        var result_m = devices.wNode.Where(p => p.uNID == MuNID)
        .SelectMany(x => x.PFO);
        var result_s = devices.wNode.Where(p => p.uNID == MuNID)
        .SelectMany(x => x.sNode)
            .SelectMany(x => x.PFO);
        var combined = result_m.Union(result_s)
            .SelectMany(x => x.Folio)
            .SelectMany(x => x.nF)
            .Where(x => x.Ind == nFIndex);

        return combined.FirstOrDefault();
     }

This also works. Presumably it compiles to the same thing?

  public nF GetValuebyuNidIndex1(dev devices, UInt32 MuNID, ushort nFIndex)
    {
        var result_m = from dd in devices.wNode
                       where dd.uNID == MuNID
                       from pfo in dd.PFO
                       select pfo;
        var result_s = from dd in devices.wNode
                       where dd.uNID == MuNID
                       from snode in dd.sNode
                       from pfo in snode.PFO
                       select pfo;
        var combined = result_m.Union(result_s);
        var result = from cc in combined
                     from ff in cc.Folio
                     from nn in ff.nF
                     where nn.Ind == nFIndex
                     select nn;
        return result.FirstOrDefault();
    }

Upvotes: 0

Linus Caldwell
Linus Caldwell

Reputation: 11058

Not sure if this code will work (testing would take time), but something like that should do the trick:

var resultMaster = devices.Master.SelectMany(y => y.PFO);
var resultSlave = devices.Slave.SelectMany(y => y.PFO);
var result = resultMaster.Union(resultSlave)
                         .SelectMany(z => z.Folio)
                         .SelectMany(a => a.Subfolio)
                         .Where(b=>b.Ind==32);

It's 3 parts for readability, but the query will be executed as one.

Upvotes: 1

Related Questions