Reputation: 1924
In my code Entity Framework load only one navigation property
//Model
public class MemorialData
{
public MemorialData()
{
Id = Guid.NewGuid();
}
[Key]
public Guid Id { get; set; }
public virtual Memorial Memorial { get; set; }
public Guid MemorialId { get; set; }
public virtual UserData Author { get; set; }
public Guid AuthorId { get; set; }
public string Data { get; set; }
}
public ActionResult AddData(MemorialData model)
{
MemorialData md = db.MemorialDatas.Find(model.Id);
if (md == null)
{
System.Diagnostics.Debug.WriteLine("md == null Creating");
md = new MemorialData();
md.MemorialId = model.MemorialId;
//md.Memorial = db.Memorials.Find(model.MemorialId);
md.Data = model.Data;
md.AuthorId = db.CurrentUser.Id;
db.MemorialDatas.Add(md);
}
else
{
md.Data = model.Data;
}
System.Diagnostics.Debug.WriteLine("Saving " + md.Id);
db.SaveChanges();
System.Diagnostics.Debug.WriteLine("Load " + md.Id);
md = db.MemorialDatas.Find(md.Id);
System.Diagnostics.Debug.WriteLine("AuthorId " + md.AuthorId);
System.Diagnostics.Debug.WriteLine("Author is NULL? " + (md.Author == null));
System.Diagnostics.Debug.WriteLine("MemorialId " + md.MemorialId);
System.Diagnostics.Debug.WriteLine("Memorial is NULL? " + (md.Memorial == null));
}
Debug output
md == null Creating
Saving 1b21f49f-749d-4cd3-8c3f-1f128ce67f6f
Load 1b21f49f-749d-4cd3-8c3f-1f128ce67f6f
AuthorId 7b1fc9c4-4930-45be-9196-44b3f49e6770
Author is NULL? False
MemorialId a813a8f4-409b-4c97-8d2d-cb19aff267bb
Memorial is NULL? True ???
Why Memorial is null but Author not null?
Where to find the cause of the error?
P.S.
If uncomment //md.Memorial = db.Memorials.Find(model.MemorialId);
Memorial is NULL? False ???
Upvotes: 1
Views: 312
Reputation: 177163
I assume that db.CurrentUser
is a User
entity. Apparently in your AddData
method this entity is already loaded because you are using:
md.AuthorId = db.CurrentUser.Id;
(If not, you would get a NullReferenceException
.)
When you set the AuthorId
EF will set the Author
navigation property as well when DetectChanges
is called (happens inside of db.MemorialDatas.Add
) because the Author
(=db.CurrentUser
) is in memory and probably attached to the context.
The Memorial
entity is not loaded, you seem to have only the model.MemorialId
available.
Your test to write and read the MemorialData
happens in the same context and ...
md = db.MemorialDatas.Find(md.Id);
...doesn't run a database query because you have added it to the context before, hence Find
can return it from memory with md.Author
being set.
md.Memorial
is not set and when you access it EF won't run a lazy loading query because you didn't create a dynamic proxy but just a plain Entity with md = new MemorialData()
.
In order to fix the problem and to enable lazy loading so that md.Memorial
can be loaded from the database you must create a dynamic proxy (instead of md = new MemorialData();
):
md = db.MemorialDatas.Create();
Upvotes: 3