Reputation:
I've been trying to grok EF many-to-many relationships for the past two days now and I'm still missing something even after scouring a dozen different questions here.
I've got a model named Text
that can have an arbitrary number of Tag
models associated with it, and obviously, at least in theory, each Tag
can be associated with an arbitrary number of Texts. Entity Framework seems to understand this well enough to create a table named TextTags in the database without me asking it to do so, and I can access Text.Tags
without trouble, but when I attempt to access Tag.Texts
in my code, I get a null reference exception.
Now, I could just add every text to every tag manually (or could I? that seems to throw some kind of error), but that would seem to defeat the purpose... Besides which, it also seems error prone. What am I failing to understand?
Code as requested:
Text model:
public class Text
{
public int ID { get; set; }
public Author Author { get; set; }
public string Content { get; set; }
public virtual ICollection<Tag> Tags { get; set; }
}
Tag model:
public class Tag
{
public int ID { get; set; }
public string Name { get; set; }
public ICollection<Text> Texts { get; set; }
}
Data insert:
using (var db = new TextDbContext())
{
db.Authors.Add(new Author()
{
Name = "Poe"
});
db.Tags.Add(new Tag() { Name = "lame" });
db.Tags.Add(new Tag() { Name = "example" });
db.SaveChanges();
db.Texts.Add(new Text()
{
Author = db.Authors.First(),
Tags = db.Tags.ToList(),
Content = "This is the first text by Poe."
});
db.Texts.Add(new Text()
{
Author = db.Authors.First(),
Tags = db.Tags.ToList(),
Content = "This is the second text by Poe."
});
db.Texts.Add(new Text()
{
Author = db.Authors.First(),
Tags = db.Tags.ToList(),
Content = "This is the third text by Poe."
});
db.SaveChanges();
}
Error:
foreach (var tag in db.Tags)
{
foreach (var text in tag.Texts)
{
Console.WriteLine("Tag: {0}\tText: {1}", tag.Name, text.Content);
// Null reference on line above.
}
}
Upvotes: 1
Views: 240
Reputation: 177153
You get a NullReferenceException
because your navigation property Tag.Texts
is not marked as virtual
. As a result lazy loading does not work to load the Tag.Texts
collection when you access it and the collection is null
. (Text.Tags
is virtual
, hence no exception here.)
Upvotes: 4