Given a POCO model and Code First, after setting a foreign key property on an instance that has an associated navigation property, fix-up is supposed to occur during DetectChanges. If code causes another navigation property to be lazy-loaded on that instance then the fix-up does not occur.
This appears to be a bug in DetectChanges. From what I can tell this issue exists in all versions of EF since 4.1.
The attached solution demonstrates the problem.
Comments: Fixed in 60fec95f8eec CurbYourEnthusiasm (Make FK fixup on loading less aggressive) This is a fix for CodePlex 668: DetectChanges navigation property fix-up bug? As noted following the investigation, this was not actually a bug because DetectChanges should have been called before the load was made. However, this is a bit ambiguous with lazy loading because the lazy loading call is not an explicit call into the EF APIs. So the fix here makes lazy loading less likely to behave badly if DetectChanges has not been called. In this particular problem there are two navigation properties each with their own FK. Setting the FK for the first (let's call it the broken relationship) and then lazy loading the second (let's call it the working relationship) without first calling DetectChanges will then prevent lazy loading of the second. All the following need to be true to hit this particular problem: - The broken relationship must start out in the loaded state. In the repro this is the cause because its FK is null, which means EF knows that there is nothing in the database to load and so sets IsLoaded to true. - The FK of the broken relationship must be changed before lazy loading the working relationship - DetectChanges must not have been called after changing the FK What happens in this situation is that when the working relationship is lazy loaded EF does FK fixup on the entities at both ends of the relationship. While looking through the FKs it caches the FK of the broken relationship. Because this cached value is updated it means that DetectChanges later does not see the change. If the broken relationship was not marked as loaded this would not matter for loading. But because DetectChanges does not see the FK change it does not flip the relationship to not loaded. Therefore it does not load. The fix is to make FK fixup on loading only consider FKs for the relationship that has actually been loaded. This therefore prevents the cached FK from being updated, and DetectChanges is then able to fuction correctly.
This appears to be a bug in DetectChanges. From what I can tell this issue exists in all versions of EF since 4.1.
The attached solution demonstrates the problem.
Comments: Fixed in 60fec95f8eec CurbYourEnthusiasm (Make FK fixup on loading less aggressive) This is a fix for CodePlex 668: DetectChanges navigation property fix-up bug? As noted following the investigation, this was not actually a bug because DetectChanges should have been called before the load was made. However, this is a bit ambiguous with lazy loading because the lazy loading call is not an explicit call into the EF APIs. So the fix here makes lazy loading less likely to behave badly if DetectChanges has not been called. In this particular problem there are two navigation properties each with their own FK. Setting the FK for the first (let's call it the broken relationship) and then lazy loading the second (let's call it the working relationship) without first calling DetectChanges will then prevent lazy loading of the second. All the following need to be true to hit this particular problem: - The broken relationship must start out in the loaded state. In the repro this is the cause because its FK is null, which means EF knows that there is nothing in the database to load and so sets IsLoaded to true. - The FK of the broken relationship must be changed before lazy loading the working relationship - DetectChanges must not have been called after changing the FK What happens in this situation is that when the working relationship is lazy loaded EF does FK fixup on the entities at both ends of the relationship. While looking through the FKs it caches the FK of the broken relationship. Because this cached value is updated it means that DetectChanges later does not see the change. If the broken relationship was not marked as loaded this would not matter for loading. But because DetectChanges does not see the FK change it does not flip the relationship to not loaded. Therefore it does not load. The fix is to make FK fixup on loading only consider FKs for the relationship that has actually been loaded. This therefore prevents the cached FK from being updated, and DetectChanges is then able to fuction correctly.