Wait, what about Id?

You may be surprised that we’re not accepting the never-null Id property via the constructor as well. We leave it out for good reason.

First, as a value type, we have no warning about it; it will simply default to the empty value.

Second, we know that EF would prefer to own our Id properties. If we want to perform an INSERT, for instance, EF wants us to construct the entity without bothering with the Id, Add(…) it, and then save those changes. EF will know what to do and will populate our Id when it’s good and ready. Likewise, on a SELECT, EF will fill it in before we ever look at it.

Our entity class is a little more verbose now, but it’s also doing a better job of telling the next developer how it should be used. We’re saying, “You really need at least these values to be valid, and you really should keep your hands off that Id property.”

Conclusion: A Mixed Bag

Enabling Nullable Reference Types is going to challenge some long-held bad habits around “good enough” coding patterns, like leaving entities poorly initialized. That can hurt at first, but it’s a clear step towards correctness.

It’s also going to hand us some ugliness in the form of syntax like “default!”. It’s a shame that we’ll have to put that on every DbSet, but at least it’s a pattern you can learn quickly and that is contained in a single file.

Most importantly, as you explore the feature in your own projects, stop at each warning, consider what it’s really telling you about what can go wrong in your system, and only then decide how to react to resolve the warning.

This blog post was part of C# Advent 2019.