1.) I have a problem (lack of knowledge probably) on prefetching nested entities.

My Entity has a reference to Entity which has EntitySet (A.B.C; A = Entity, B = Entity and C = EntitySet)

I Would like to prefetch nested EntitySet (C) with all of its properties.

Can you help?

2.) Can Lazzy loading be used on disconnectedState? How?

Many Thanks, Sandi

This thread was imported from our support forum. The original discussion may contain more detailed answer. Original topic by Zgckula.

asked Mar 03 '10 at 12:28

Editor's gravatar image


One Answer:

Alex (Xtensive) wrote:

1) Prefetch works absolutely the same way with DisconnectedState. The only thing you must remember is that Connect() must be used to make direct queries. So:

var ds = ...; // DisconnectedState
var session = ...; // Session
// Assuming ds is attached to session
var alphas = ... // IEnumerable<A>

// Prefetching A.B, A.B.C
using (ds.Connect()) {
    .PrefetchSingle(a => a.B, // 1-to-1 association
      betas => betas
        .Prefetch(b => b.C, int.MaxValue)); // EntitySet with the limit on number of items to be loaded

Alex (Xtensive) wrote:

Another alternative:


using (ds.Connect()) {
  var query =
    from a in alphas
    let b = a.B
    select new {a, b, b.C};
  query.Run(); // An extension method iterating over any IEnumerable<T>

The result of this code must be identical from the point of fetched objects, but this approach is actually a bit more effecient:

-A.B relationship is fetched with JOIN

-B.C relationship is fetched with use of future queries. See http://blog.alexyakunin.com/2009/11/new ... ching.html

First approach implies everything is fetched with future queries, but A.B relationship is fetched with ~ a set of "... WHERE ... IN (...)" queries. We use nearly the same approach is for local collections support here:

Alex (Xtensive) wrote:

  1. Yes, it will work inside ds.Connect() block. But note that currently there is just one transaction for each of such blocks, so generally, you should close them fast. We'll try to suggest an alternative approach here ASAP (I described it in another your post).

Denis Krjuchkov (Xtensive) wrote:

Hello, Sandi. This is a feature. Let me explain theoretical part first. There are two ElementAt extension methods. One for IEnumerable<t> and one for IQueryable<t>. IQueryable is a subtype for IEnumerable. When you write something.ElementAt(0) compiler automatically chooses the best matching extension method. Our EntitySets implement IQueryable interface, so extension method for IQueryable is called. IQueryable is an entry point for LINQ to anything except regular collections. In our case it is an entry point for database queries. Actually calling

b.c.ElementAt(0); is a shortcut for

Query.All<C>().Where(c => c.Owner == b).ElementAt(0);

However, it seems you want to use ElementAt extension method for IEnumerable rather than for IQueryable. There is a standard helper for this. Consider using AsEnumerable. It does nothing but upcast from IQueryable to IEnumerable.


ToArray works pretty well because there is no such extension method for IQueryable, so extension method for IEnumerable is used.

Alex (Xtensive) wrote:

Worse: b.c.ElementAt(someIndex); is actually a shortcut for:

Query.All<C>().Where(c => c.Owner == b).Skip(someIndex).First();

That's just FYI ;)

answered Mar 03 '10 at 13:26

Editor's gravatar image


Zgckula wrote: Thanks!

I have prefetched correctly myself for the first time but obviously i was misled by the following bug:

a.b.c.ElementAt(0) wants to connect and throws exception

a.b.c.ToArray()[0] works fine

Regards, Sandi

(Mar 03 '10 at 13:26) Editor Editor's gravatar image
Your answer
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!
toggle preview

powered by OSQA