I have a self-referencing entity:
When I query this entity..
var query = this._context.DispositionPossibilities
.Where(x => x.AreaID == areaID)
.Where(x => x.IsActive == true);
.. the resulting collection has EVERY item returned from the query at the root, and then the those items with ParentIDs are 'duplicated' inside the child collections (because of Navigation Properties).
I can remove them by doing this:
// have to ToArray() first because the child entities will be excluded if I don't..
rValue = query.ToArray();
// trim off the entities at the root that shouldn't be there..
rValue = rValue.Where(x => !x.ParentCode.HasValue).ToArray();
.. But is there a better way to do this?
[EDIT]
My original Include
solution below does not traverse the entire hierarchy. This should've been obvious to me, but it will only return the FIRST level of the hierarchy.
Since I will be making this call per-tree at most once per day, I'll take the performance hit.
That said, I did come up with a better way to strip the non-root elements off the hierarchy:
var subset = new List<DispositionPossibility>();
foreach (var disp in query.OrderBy(x => x.ParentCode).ToArray())
{
if (!disp.ParentCode.HasValue)
subset.Add(disp);
else
break;
}
This wound up being .4-.7 seconds faster than the first method I was using. (So almost as good as the Include method, but actually giving me all levels.)
Adding the ASC sort and breaking out of the loop shaved .1-.25 seconds off my 27k item trees.
After not looking at this for a day and coming back to it, it took all of 5 seconds to think of how to do this.
var query = context.DispositionPossibilities
.Include("ChildDispositions")
.Where(x => x.AreaID == areaID)
.Where(x => !x.ParentCode.HasValue)
.Where(x => x.IsActive == true);
I ran code profiling, and this method performs better in almost every case:
-- Most notably for my largest trees with 4 levels and ~27,400 items by roughly .73 to .83 seconds.
-- For small trees (<5,000), the difference was far less noticeable (less than .01 - .05 seconds)