Quantcast
Channel: Entity Framework
Viewing all articles
Browse latest Browse all 10318

Commented Issue: EF loads entire child collection when item is added to context [683]

$
0
0
I've found that when using lazy child collections, the collection is loaded when an item is added directly to the context. This is a problem because the collection may be very large. I think EF wants to update the in memory collection with the new item, but it should realize that Í didn't request the collection.<br /><br />One workaround is to make the property non virtual. Another is to make the parent class internal (WTF!?)<br /><br />Here's code that reproduces the issue. Put a breakpoint in the last Add() call and confirm with SQL Server Profiler that all citizens (possible million, depends on the country) are loaded.<br /><br />public class Country // make internal to avoid spurious select<br />{<br /> public virtual int CountryID { get; set; }<br /><br /> public virtual ICollection<Citizen> Countries { get; set; } // make non virtual to avoid select<br />}<br />public class Citizen<br />{<br /> public virtual int CitizenID { get; set; }<br /><br /> public virtual int CountryID { get; set; }<br />}<br />class Context : DbContext<br />{<br /> public DbSet<Country> Countries { get; set; }<br /> public DbSet<Citizen> Citizens { get; set; }<br />}<br />class Program<br />{<br /> static void Main()<br /> {<br /> using (var db = new Context())<br /> {<br /> db.Countries.Add(new Country());<br /> db.SaveChanges();<br /> }<br /> using (var db = new Context())<br /> {<br /> var c = db.Countries.FirstOrDefault();<br /> db.Citizens.Add(new Citizen { CountryID = c.CountryID, }); // loads all citizens of the country<br /> }<br /> }<br />}<br />
Comments: Try this revised code static void Main() { using (var db = new Context()) { db.Database.Delete(); var country = new Country(); db.Countries.Add(country); for (int i = 0; i < 10; ++i) { db.Citizens.Add(new Citizen { CountryID = country.CountryID, }); } db.SaveChanges(); } using (var db = new Context()) { var country = db.Countries.Single(); db.Citizens.Add(new Citizen { CountryID = country.CountryID, }); // loads all citizens of the country } } The last line runs this query: exec sp_executesql N'SELECT [Extent1].[CitizenID] AS [CitizenID], [Extent1].[CountryID] AS [CountryID] FROM [dbo].[Citizens] AS [Extent1] WHERE [Extent1].[CountryID] = @EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=1 which retrieves the 10 citizens added in the previous session.

Viewing all articles
Browse latest Browse all 10318

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>