I have an Item
. Item
has a Category
.
Category
has ID
, Name
, Parent
and Children
. Parent
and Children
are of Category
too.
When I do a LINQ to Entities query for a specific Item
, it doesn't return the related Category
, unless I use the Include("Category")
method. But it doesn't bring the full category, with its parent and children. I could do Include("Category.Parent")
, but this object is something like a tree, I have a recursive hierarchy and I don't know where it ends.
How can I make EF fully load the Category
, with parent and children, and the parent with their parent and children, and so on?
This is not something for the whole application, for performance considerations it would be needed only for this specific entity, the Category.
@parliament gave me an idea for EF6. Example for Category with Methods to load all parents up to root node and all children.
NOTE: Use this only for non performance critical operation. Example with 1000 nodes performance from http://nosalan.blogspot.se/2012/09/hierarchical-data-and-entity-framework-4.html.
Code:
You could also create a tablevalued function in the database and add that to your DBContext. Then you can call that from your code.
Instead of using the
Include
method you could useLoad
.You could then do a for each and loop through all the children, loading their children. Then do a for each through their children, and so on.
The number of levels down you go will be hard coded in the number of for each loops you have.
Here is an example of using
Load
: http://msdn.microsoft.com/en-us/library/bb896249.aspxIf you definitely want the whole hierarchy loaded, then if it was me I'd try writing a stored procedure who's job it is to return all the items in a hierarchy, returning the one you ask for first (and its children subsequently).
And then let the EF's relationship fixup ensure that they are all hooked up.
i.e. something like:
If you've written your stored procedure correctly, materializing all the items in the hierarchy (i.e.
ToList()
) should make EF relationship fixup kicks in.And then the item you want (First()) should have all its children loaded and they should have their children loaded etc. All be populated from that one stored procedure call, so no MARS problems either.
Hope this helps
Alex
You chould rather introduce a mapping table that maps each Category a parent and a child, instead of adding the parent and child property to the cargo itself.
Depending on how often you need that information it can be queried on demand. Via unique constraints in the db you can avoid an infinite amount of relationships beeing possible.
You don't want to do recursive loading of the hierarchy, unless you are allowing a user to iteratively drill down/up the tree: Every level of recursion is another trip to the database. Similarly, you'll want lazy loading off to prevent further DB trips as you're traversing the hierarchy when rendering to a page or sending over a webservice.
Instead, flip your query: Get
Catalog
, andInclude
the items in it. This will get you all items both hierarchically (navigation properties) and flattened, so now you just need to exclude the non-root elements present at the root, which should be pretty trivial.I had this problem and provided a detailed example of this solution to another, here