Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework 3.5 - How to load children

My questions is probably very simple, how do you load children/subclasses. There is no "load" or anything like it that I can find to have the context load the children.

the context class is of ObjectContext type, see below:

public partial class RTIPricingEntities : global::System.Data.Objects.ObjectContext

Product

Product.ModifiedByUser (how to load this class, when loading product??)

Product.Category (how to load the categories when loading product?)

like image 980
Jukeman Avatar asked Sep 03 '09 16:09

Jukeman


3 Answers

You can eager load:

var q = from p in Context.Products
                  .Include("ModifiedByUser")
                  .Include("Category")
        select p;

...or project:

var q = from p in Context.Products
        select new 
        {
           Id = p.Id,
           Name = p.Name
           ModifiedByUserName = p.ModifiedByUser.Name,
           CategoryName = p.Category.Name
        }

The advantage of projection is you get only the data you need, not the whole of every referenced entity. Advantage of eager loading is that returned entities do change tracking. Pick the right technique for the problem at hand.

Update

Yes, it is important to mention that you are using RIA Services. I presume you're also working within the client. This makes things completely different.

In RIA Services, it is very important to make sure that you return the entire graph of entities you require in the initial load. You don't want to call anything like .Load() on an entity, because that would be another hot to the server, which is bad for performance. If you are in, for example, a Silverlight client and request a list of instances from the server and their related properties are not already materialized, it is already too late. Also, Include will not work within a Silverlight client. Therefore, RIA Services has server-side tools you can use to ensure that you return the correct, fully materialized object graph initially.

What you need to do instead is used IncludeAttribute inside your RIA Services server. You can create a "buddy" metadata class to decorate your entity model with [Include]. There are examples in the RIA Services overview document, section 4.8.

like image 177
Craig Stuntz Avatar answered Nov 07 '22 12:11

Craig Stuntz


Using the .Include() as many others have suggested is a great way to achieve what you need.

However, sometimes you might need to "re-load" something later on that you didn't "include", or that you only need sometimes, so putting an Include statement might be a waste of computing cycles in many cases.

In case of a singular relationship like "Product.Category" (where Product.Category is your navigation property from product to category), you most likely also have a "Product.CategoryReference" element. You can check that to see if it's loaded or not, and if not, you can load it "on demand":

if(!Product.CategoryReference.IsLoaded)
{
    Product.CategoryReference.Load();
}

Now your referenced "Category" should be in memory and ready to use.

If you have a navigation property which references a collection of things (e.g. "Parts" for a product), you can do the same thing, directly on the navigation property:

if(!Product.Parts.IsLoaded)
{
    Product.Parts.Load();
}

That can be a useful technique for "loading on demand" of single or collection type navigation properties if you haven't "included" them into your EF query.

Marc

like image 8
marc_s Avatar answered Nov 07 '22 10:11

marc_s


You can use the Include() method of the System.Data.Objects.ObjectQuery. This method specifies the related objects to include in the query results and calls to Include() can be chained together to load multiple related objects.

For example to load ModifiedByUser and Category you would use a query like this:

var q = from p in context.Products.Include("ModifiedByUser").Include("Category") 
        select p;

If your Category entity also had a ModifiedByUser entity that you wanted to load you would use a query like this:

var q = from p in context.Products
              .Include("ModifiedByUser")
              .Include("Category.ModifiedByUser") 
        select p;

See Shaping Query Results on MSDN for further examples.

like image 3
Daniel Richardson Avatar answered Nov 07 '22 11:11

Daniel Richardson