views:

2105

answers:

4

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?)

+4  A: 

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.

Craig Stuntz
Hello, I dont know if we have the same version, but neither option is possible when im coding it. There is no ".Include" available, only "Intersect" .. im using entityframework derived entities which has "ObjectContext" as its base class.. And when I project, there are no properties in the intellisense for me to set..
Jukeman
Include is a method of ObjectQuery<T>, not IQueryable<T>. So check the type of the reference you have. Entities don't derive from ObjectContext, they derive from EntityObject. In my example there won't be any IntelliSense on the projected object because I used an *anonymous* type. If I had used a non-anonymous type there would be IntelliSense.
Craig Stuntz
+1  A: 

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.

Daniel Richardson
I see this solution quite a bit, so I must be doing something totally different than everyone else. Basically, I am using the context from the datamodel that was generate by the entityframework. I have the latest of .Net. There is no "Include" availbale. Are you using dbml/linq in this example? Im thinking this is why its different...
Jukeman
A: 

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

marc_s
Thanks everyone, I realized that the reason I wasn't able to implement the many proposed solutions is because the context is different once converted by the domain service for silverlight. In the code behind of the entity framework data model I can implement all of your solutions and I just found that out. But thanks to your help, I knew that the issue had to be that I was looking in the wrong place...
Jukeman
A: 

Hi All, I have noticed that the above mentioned solution by Craig does not load both the ModifiedByUser and Category. It only loads the last object collection which in this case is "Category".

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

However, if you swap the order, to make it .Include("Category").Include("ModifiedByUser"), then "ModifiedByUser" is loaded. The wierd thing is that the IsLoaded property of both the object collection will show "true", however the Count for the first object collection will always be zero. Not sure why this is the case.

Johnson