Ef Codefirst: Should I Initialize Navigation Properties

EF codefirst : Should I initialize navigation properties?

Collections: It doesn't matter.

There is a distinct difference between collections and references as navigation properties. A reference is an entity. A collections contains entities. This means that initializing a collection is meaningless in terms of business logic: it does not define an association between entities. Setting a reference does.

So it's purely a matter of preference whether or not, or how, you initialize embedded lists.

As for the "how", some people prefer lazy initialization:

private ICollection<Address> _addresses;

public virtual ICollection<Address> Addresses
{
get { return this._addresses ?? (this._addresses = new HashSet<Address>());
}

It prevents null reference exceptions, so it facilitates unit testing and manipulating the collection, but it also prevents unnecessary initialization. The latter may make a difference when a class has relatively many collections. The downside is that it takes relatively much plumbing, esp. when compared to auto properties without initialization. Also, the advent of the null-propagation operator in C# has made it less urgent to initialize collection properties.

...unless explicit loading is applied

The only thing is that initializing collections makes it hard to check whether or not a collection was loaded by Entity Framework. If a collection is initialized, a statement like...

var users = context.Users.ToList();

...will create User objects having empty, not-null Addresses collections (lazy loading aside). Checking whether the collection is loaded requires code like...

var user = users.First();
var isLoaded = context.Entry(user).Collection(c => c.Addresses).IsLoaded;

If the collection is not initialized a simple null check will do. So when selective explicit loading is an important part of your coding practice, i.e. ...

if (/*check collection isn't loaded*/)
context.Entry(user).Collection(c => c.Addresses).Load();

...it may be more convenient not to initialize collection properties.

Reference properties: Don't

Reference properties are entities, so assigning an empty object to them is meaningful.

Worse, if you initiate them in the constructor, EF won't overwrite them when materializing your object or by lazy loading. They will always have their initial values until you actively replace them. Worse still, you may even end up saving empty entities in the database!

And there's another effect: relationship fixup won't occcur. Relationship fixup is the process by which EF connects all entities in the context by their navigation properties. When a User and a Licence are loaded separately, still User.License will be populated and vice versa. Unless of course, if License was initialized in the constructor. This is also true for 1:n associations. If Address would initialize a User in its constructor, User.Addresses would not be populated!

Entity Framework core

Relationship fixup in Entity Framework core (2.1 at the time of writing) isn't affected by initialized reference navigation properties in constructors. That is, when users and addresses are pulled from the database separately, the navigation properties are populated.

However, lazy loading does not overwrite initialized reference navigation properties.

In EF-core 3, initializing a reference navigation property prevents Include from working properly.

So, in conclusion, also in EF-core, initializing reference navigation properties in constructors may cause trouble. Don't do it. It doesn't make sense anyway.

EF core 3.1: should I initialize list navigation properties when using eager loading to load related entities?

This is not useful and you don't have to do this because you are using eager loading(which is not very efficient if you load a lot of unnecessary data but this is another topic).

However, this is useful in two cases:

  • If you don't use eager loading because Posts property may be null
  • You are creating a new Blog object which is not yet saved in database and want to add a new Post into it. In this case Posts property must be initialized prior Posts.Add(post) is called because null ref unitialized exception will be thrown.

EF Core | Need to use Navigation property for update on one property, but not another (Modules)

From Progman

I did not need to set the Module and FileSystemItemData in my constructor for FileSystemItems:

        /// <summary>
/// Initializes a new instance of the <see cref="FileSystemItems"/> class.
/// </summary>
public FileSystemItems()
{
ItemChildren = new HashSet<FileSystemItems>();
}

EF Code First - Models , when should properties be instantiated in constructor?

You never need to instantiate a property in the models constructor for EF to work, but it make it more convenient.

For example, If you had a class Order and it has children of Order Detail, and you wanted to add a new Order to your database.

Without initializing OrderDetails

var order = new Order();
order.OrderDetails.Add(new OrderDetail()); // this would error because OrderDetails is null

One option could be to call order.OrderDetails = new List();
before you use Add(), but then you would need to have that code repeated everywhere you wanted to use Add(). Instead you can put that code in the constructor, and then OrderDetails will be ready to use with all newly created Orders.

Entity Framework 6 navigation collections are null instead of empty

As the official documentation demonstrates, you should always initialize your collection navigation properties inside the entity constructor if you want to prevent a Null reference exception.

public Subject()
{
Students = new HashSet<Student>(); // you may also use List<Student>, but HashSet will guarantee that you are not adding the same Student mistakenly twice
}

Entity framework will fill Students property (using a proxy) only if there is at least a student, else it will leave the property as is (null if you have not initialized it).

When the entity is not a proxy, then Entity Framework tracks its changes only when calling SaveChanges() on the context, using its original entity state for comparison. This answer will further clarify this behavior.

Entity Framework 5 - code first array navigation property one to many with Interface Type

I can't access the link in your comment, but I assume you changed

public virtual ICommentInfo[] Comments { get; set; }

into the common way to define navigation properties:

public virtual ICollection<CommentInfo> Comments { get; set; }

because entity framework does not support interfaces in its conceptual model.

The exception about the disposed context means that you access this property after fetching Post objects from the database and disposing the context. This triggers lazy loading while the connection to the database is lost. The solution is to use Include:

var posts = context.Posts.Include(p => p.Comments).Where(...)

Now posts and comments are fetched in one go.



Related Topics



Leave a reply



Submit