monty
monty

Reputation: 8755

Entity Framework Core: combining multiple result objects into one collection

I am facing this linq query for entity framework core (2.0).

  var result = await dbContext.Table1DbSet
.Where(t1e => t1e.Id == id && t1e.Id2 == id2)
.Select
(
  t1e =>
  t1e.Table2NavPropICollection.Select
  (
    t2e => new
    {
      singleObject = t2e.Table3NavPropObject.TargetObject,
      enumerable1  = t2e.Table3NavPropObject.Table4NavPropObject.Table5NavPropICollection.Select(t5e => t5e.TargetObject),
      enumerable2  = t2e.Table3NavPropObject.Table6NavPropObject.Table7NavPropICollection.Select(t7e => t7e.TargetObject),
      enumerable3  = t2e.Table3NavPropObject.Table8NavPropICollection.SelectMany(t8e => t8e.Table9NavPropICollection.Select(t9e => t9e.TargetObject))
    }
  )
)
.ToListAsync();

The goal is to query all the referenced instances of TargetObject which is referenced accros ~ 10 different tables.

Currently it returns an IEnumerable where the anonymous object contains the properties singleObject, enumerable1, enumerable2, enumerable3. All those properties are of type TargetObject or IEnumerable.

Can I, and how, rewrite the query to not return anonymous objects but just an IEnumerable containing all the values?

For some reason the compiler won't let me iterate over the anonymous collection and flatten it manually.

Upvotes: 0

Views: 103

Answers (2)

Derpy
Derpy

Reputation: 1528

This should do the trick if you want one array per t1e row.

      var result = await dbContext.Table1DbSet
    .Where(t1e => t1e.Id == id && t1e.Id2 == id2)
    .Select
    (
      t1e =>
      t1e.Table2NavPropICollection.Select
      (
        t2e => new[] {t2e.Table3NavPropObject.TargetObject}.Concat(
            t2e.Table3NavPropObject.Table4NavPropObject.Table5NavPropICollection.Select(t5e => t5e.TargetObject)).Concat(
            t2e.Table3NavPropObject.Table6NavPropObject.Table7NavPropICollection.Select(t7e => t7e.TargetObject)).Concat(
            t2e.Table3NavPropObject.Table8NavPropICollection.SelectMany(t8e => t8e.Table9NavPropICollection.Select(t9e => t9e.TargetObject)))
      )
    )
    .ToListAsync();

If you want it completely flat, you'll want to switch that Select to a SelectMany().

      var result = await dbContext.Table1DbSet
    .Where(t1e => t1e.Id == id && t1e.Id2 == id2)
    .SelectMany
    (
      t1e =>
      t1e.Table2NavPropICollection.Select
      (
        t2e => new[] {t2e.Table3NavPropObject.TargetObject}.Concat(
            t2e.Table3NavPropObject.Table4NavPropObject.Table5NavPropICollection.Select(t5e => t5e.TargetObject)).Concat(
            t2e.Table3NavPropObject.Table6NavPropObject.Table7NavPropICollection.Select(t7e => t7e.TargetObject)).Concat(
            t2e.Table3NavPropObject.Table8NavPropICollection.SelectMany(t8e => t8e.Table9NavPropICollection.Select(t9e => t9e.TargetObject)))
      )
    )
    .ToListAsync();

Upvotes: 1

RickardN
RickardN

Reputation: 548

Is Add and/or Concat a possible solution?

PoC:

var a = new [] { 1,2,3 };

var result = new {
    firstA = a.First(),
    otherAs = a,
    backwards = a.Reverse()
};

var final = new List<int>();
final.Add(result.firstA);
final.Concat(result.otherAs.Concat(result.backwards))
    .Dump();

Upvotes: 0

Related Questions