views:

24

answers:

1

I need to be to create an entity data model in the EF version 1, because my web host doesn't have Framework 4.0 yet. Below is just a simple example to show the problem.

I have 3 tables, one Users table, another Webpages table, and one table with Visits. The former two tables each have a one-to-many relationship with the Visits table (which basically works as a many-to-many relationship, only the Visits table has its own primary key and extra fields)

With the 4.0 version this works, but it doesn't with v.1. "Visits" has a count of 0, so the test string returns ""... Why, and how would I be able to access the foreign key relation in v.1?

UsersEntities context = new UsersEntities();
var users = context.Users;
string result = "";
foreach (var user in users)
{
    foreach (var visit in user.Visits)
    {
        result += visit.Webpage.Url + "\n";
    }
}

So the foreach loop loops through the users, which it gets ok, but the inner loop is never entered because there are no Visits returned. Again, in Framework 4.0 it works fine, using the same database.

So what's wrong?

+2  A: 

Simply change your code to this:

UsersEntities context = new UsersEntities(); 
var users = context.Users.Include("Visits"); 
string result = ""; 
foreach (var user in users) 
{ 
    foreach (var visit in user.Visits) 
    { 
        result += visit.Webpage.Url + "\n"; 
    } 
} 

Notice the Include(...) that tells EF to eagerly load each User's visits.

With that in place it should work.

Actually if Webpage is a navigation too, you might need:

Include("Visits.Webpage");

Hope this works

Alex James
Terrific! It works great, thanks!Just a couple of questions: why was this necessary? It's not necessary in Linq to Sql, and not in v.4.0, so was this a shortcoming that was corrected in 4.0 or what's the purpose of this "Include"?Also, when navigating data models like this, a lot of steps ("dots") need to be traversed to get the object wanted. I'm thinking of the principle of least knowledge, or the "Law of Demeter" which says you should avoid this. Is this a problem? I don't see how to do it otherwise... (I ask because I try to learn more about design principles).
Anders Svensson
Well in L2S when you access a navigation it is silently loaded - aka lazyloading.As for the law of Demeter, I have yet to see an ORM that allows you to collapse navigations to avoid this violation. i.e. x.YZ instead of x.Y.Z
Alex James
You use Include when you know in advance you will need some data - lazyloading - is useful when you pull back a lot of results, and maybe just need a related item from only a few of the results. I.e. pulling back all the data up front is a waste.
Alex James
Ok, thanks! Your answers helped a lot!
Anders Svensson