1

Let's assume I have 2 tables, A and B with 1-0..1 relation. I use the Adapter approach. I need to load a collection of A entities in one place, and then load all related B entities for all A entities later. The reason to not use Prefetch is that in most cases I will not need to load B entities.

I use LINQ everywhere, so I would like to do it the same way.

The code I am trying to write looks like this:

var linqMetadata = new LinqMetaData(adapter)
{
    ContextToUse = new Context()
};

var aCollection = linqMetadata.A.Where(/*some filter*/).ToList();

// ...

var bIds = aCollection.Select(x => x.BId);
var bCollection = linqMetadata.B.Where(x => bIds.Contains(x.BId)).ToList();

The problem is that bCollection and aCollection stay unlinked, i.e. all A entities have B = null and vice versa. I want these references to be set, and therefore the 2 graphs to be united into a single one.

I can join 2 collections using LINQ to Objects, but that's not elegant, and besides this might get much more complicated if both collections contain complex graph with interconnections that need to be established.

I can write a prefetch from B to A, but that's one extra DB query that is completely unnecessary.

Is there an easy way to get these 2 graphs merged?

Pavel Gatilov
  • 7,579
  • 1
  • 27
  • 42
  • What do you mean by that the collections "stay unlinked"? You select those items from table B the IDs of which is referred to by records in a filtered version of table A. What do you want to achieve exactly? – kol Sep 08 '14 at 13:49
  • Can you try and add a prefetch path to the master record (A) on the second query? I didn't try it but think it might get the A record from the context without querying... – Wiebe Tijsma Sep 08 '14 at 16:08
  • @kol I want references between .NET entities to be established automatically based on ids. So that after all is run, all `A` entities have non-null `B` property and vice versa. If I just run 2 queries, they are not. And this is one big difference between llblgen and some other ORMs like the EF. – Pavel Gatilov Sep 09 '14 at 07:06
  • @Zidad Thanks for the idea. Unfortunately, doesn't work. I still have the extra query. – Pavel Gatilov Sep 11 '14 at 09:43

2 Answers2

1

Object relation graph is built automatically if you add related entities using assignment for master entity and AddRange for detail entities.

Here's a pseudo-code sample:

foreach aEntity in aCollection
   aEntity.BEntity = bCollection.First(x=>x.Id == aEntity.bId);

OR

foreach bEntity in bCollection
   bEntity.AEntity.AddRange(aCollection.Where(x=>x.bId == bEntity.Id));

After doing this your object graph is complete.

brz
  • 5,926
  • 1
  • 18
  • 18
  • Sorry for the late response, but this does not work either. It works only if the graphs are linked at the master node. If there are shared nodes deeper in the graph, they are not linked. Don't know how to express this in SO comment :) – Pavel Gatilov Sep 23 '14 at 05:38
0

Since you are already using a Context, you can use PrefetchPath and context to load the PrefetchPath later, that way your entities are always linked. Then you can run a Linq2Objects query to load in-memory all B's.

var bs = aCollection.Select(x => x.B).ToList();
David Elizondo
  • 1,123
  • 1
  • 7
  • 16
  • Am I correct that this will spawn a DB query per each `A` item? – Pavel Gatilov Sep 10 '14 at 12:10
  • Thank you, but that paragraph is about re-loading an entity with additional data. It means I have to re-fetch all data that I already have which I am trying to avoid. I tried to do it that way, but it is either impossible, or I can't figure out how to. Could you post a code sample for loading a collection? – Pavel Gatilov Sep 11 '14 at 10:00