I have a problem where adding a child object to a parent object is exceptionally slow when it should not be. There are tens of thousands of child objects (33k records in this case), but none of those are children of the parent object in question.
When I add the first child to the parent it takes more than one minute to complete:
public class ParentEntity // POCO generated by EF TT4 templates
{
public virtual int Id { get; set; }
public virtual ICollection<ChildEntity> ChildEntities {}
}
public class ChildEntity // POCO generated by EF TT4 templates
{
public virtual int Id { get; set; }
public virtual int ParentEntityId { get; set; }
public virtual ParentEntity ParentEntity { get; set; }
public virtual Warehouse Warehouse { get; set; }
public virtual WarehouseLocation WarehouseLocation { get; set; }
}
public class Warehouse { // etc } // another POCO class
public class WarehouseLocation { // etc } // another POCO class
// somewhere in a controller action method...
var parent = _parentEntityService.GetBy(id);
var child = new ChildEntity{ ParentEntityId = id,
WarehouseId = id2, WarehouseLocationId = id3 };
// ChildEntities.Add() takes more than one minute to add the
// first and only child to this parent
// why would this be so incredibly slow?
parent.ChildEntities.Add(child);
What is the best way to approach finding a speed problem in EntityFramework?
Update: EFProf shows that it issues three SQL queries:
SELECT * FROM ChildEntities where ParentId = id
SELECT * FROM ChildEntities where WarehouseId = id2
SELECT * FROM ChildEntities where WarehouseLocation = id3
Why does it load these for every single ChildEntity, when it should just load them for the current child only?
Edit 2: As per @LadislavMrnka the extra queries are caused by the template's Fixup method. But when I comment out those methods and comment out the call to Fixup it is still slow. Is this not the correct way to remove the fixup (it looks like it is removed to me):
public class ChildEntity {
public virtual Warehouse Warehouse
{
get { return _warehouse; }
set
{
if (!ReferenceEquals(_warehouse, value))
{
var previousValue = _warehouse;
_warehouse = value;
//FixupWarehouse(previousValue); // commented out
}
}
}