C
C#17h ago
Faker

? operator and property assigned to =null! meaning in EF core database context

C#

using System;
using System.Collections.Generic;

namespace Learning.Models;

public partial class Book
{
public int BookId { get; set; }

public string Title { get; set; } = null!;

public string? Author { get; set; }

public string? Isbn { get; set; }

public int? PublishedYear { get; set; }

public DateTime Date { get; set; }
public string BookVersion { get; set; }

public virtual ICollection<Rental> Rentals { get; set; } = new List<Rental>();

public override string ToString()
{
return $"Title: {Title}, Author: {Author}, ISBN: {Isbn}";
}
}
C#

using System;
using System.Collections.Generic;

namespace Learning.Models;

public partial class Book
{
public int BookId { get; set; }

public string Title { get; set; } = null!;

public string? Author { get; set; }

public string? Isbn { get; set; }

public int? PublishedYear { get; set; }

public DateTime Date { get; set; }
public string BookVersion { get; set; }

public virtual ICollection<Rental> Rentals { get; set; } = new List<Rental>();

public override string ToString()
{
return $"Title: {Title}, Author: {Author}, ISBN: {Isbn}";
}
}
Hello guys, this is a book class that I scaffolded using EF Core. I have a few questions. What does that mean when we use = null! and what does that mean when we say a type of associated with ?. What does it convey in terms of database context, like nullable/ not nullable? I know that ? is used to say that we allow a data type to have null value. But what does it mean here? Also, =null basically means we are assigning null as soon as we are creating, but what does the ! mean then? Whys is the =null! important please, can we omit it?
27 Replies
Sehra
Sehra17h ago
? is the same, property can be null, mapped on database side as nullable
Angius
Angius17h ago
I know that ? is used to say that we allow a data type to have null value. But what does it mean here?
ERxactly that
Faker
FakerOP17h ago
oh ok, without the ? operator, we would have the NOT NULL constraint on the column in the database?
Angius
Angius17h ago
ye
Faker
FakerOP17h ago
ohhhh, ok, hmm what about the null! pls
Sehra
Sehra17h ago
null! is just to silence a compiler warning that a non-nullable property can be null after exiting the constructor. only doing =null would still be a warning, so null! use the null-forgiving operator to say that this null shouldn't trigger a warning
Angius
Angius17h ago
! is a null-forgiving operator, meaning "trust me bro, this is not null" Generally, using required properties is a better idea
Faker
FakerOP17h ago
yeah I see, but when we say a warning, is it something that we won't be able to run the code with? it's mandatory here?
Angius
Angius17h ago
But EF can be wonky about it
Sehra
Sehra17h ago
since the database will not allow null in the column, when it comes back it will be set to a non-null value
Angius
Angius17h ago
No, warning is just a warning
Jimmacle
Jimmacle17h ago
the problem with EF is that querying on entities with optional relationships doesn't match up with C#'s understanding of the type just because it's nullable in the C# type doesn't mean you need to check it for null in your EF LINQ queries so you have to do some level of bending NRTs to your will also, even if it's a required relationship it may still be null in the C# object if you didn't .Include the navigation
Faker
FakerOP17h ago
hmm so this give us another question :c : When to use the null! thing? Like if I've understood correctly, we are saying ok, this thing cannot be null but we are still assigning null to it but ignore the warning, we will pass a value to it later on.
Angius
Angius16h ago
Outside of ef models, never In ef models, on nav props
Sehra
Sehra16h ago
class SomeEntity {
public int OtherEntityId {get;set;}
public OtherEntity? OtherEntity {get;set;}
}
class SomeEntity {
public int OtherEntityId {get;set;}
public OtherEntity? OtherEntity {get;set;}
}
this is usually the pattern for navigation properties the id is not nullable, the full entity is. if you want it populated, include it it's mostly string messing it up since it's a reference type
Angius
Angius16h ago
Outside of nav props, I'd definitely opt for either required, or a default value Could be an empty string or a zero even, but not null!
Faker
FakerOP16h ago
I just remove the =null! in title and my IDE gives me this warning
No description
Faker
FakerOP16h ago
So the thing is, anything declared as non-nullable (we don't have the ? operator should be assigned to something at compile-time to remove the warning ?)
Sehra
Sehra16h ago
doesn't have to be set at compile time it warns if it is not set after constructor exits
Faker
FakerOP16h ago
yep I see if we don't pass a value for it in the constructor, we would get an exception?
Sehra
Sehra16h ago
nope
Jimmacle
Jimmacle16h ago
NRTs are not a runtime feature it's just for the compiler to help you avoid writing bugs nothing actually stops you from setting a non-nullable variable to null
Faker
FakerOP16h ago
yep I see Ok guys, just need to do small summary, please confirm whether the following is correct/add up to it if needed pls: 1. ? is used to explicitly say that we are expecting a particular column to be null in the database context. For example, int PublishedYear means this is a nullable field. 2. If we have reference types, like string, the default value of string and any other referenced type is null. But without the ?, we need to provide a value. We provide a value, like null then we just suppress the warning using the null-forigiving operator !. (Would have been better to use a default value here @ZZZZZZZZZZZZZZZZZZZZZZZZZ ? why pls like you said either use default value or required attribute; what does the required attribute do in this case?) 3. Also, just read about the Include() thing. Basically, the nav property which linked a particular object to another entity, that object can be null if it's not loaded; that's where it might be useful to use the ? operator. Now, in order for the object, not to be null, we use the Include() method which loads them "eagerly" something like that.
Angius
Angius16h ago
1. int PublishedYear means it is not nullable 2. Basically, yeah. And not a [Required] attribute, but a required keyword 3. Yep. Keep in mind though, that it's usually a better idea to .Select() into some DTO class rather than having a bunch of includes. Fetch only what you need.
Faker
FakerOP15h ago
yeah I see, in the DTO thing, we would have 2 queries then, like we wouldn't be able to use a single query to fetch both a subset of Book data and use that in our next query?
Angius
Angius15h ago
A single query Well, a single query to get the book and whatever related data If you wanted to, say, create a copy of this entry, that would be a second query, yeah But using .Include() would not change that
Faker
FakerOP15h ago
yep I see, thanks !

Did you find this page helpful?