-
Notifications
You must be signed in to change notification settings - Fork 226
Settings.AllowNullStrings
Makes the generated code nullable-aware: a nullable database column becomes string?, and a non-nullable one gets = null!.
| Type | bool |
| Default | false |
| Applies to | EF 6 and EF Core |
| Databases | All |
In Database.tt? |
Yes |
C# 8 introduced nullable reference types: with the feature on, string means "never null" and string? means
"may be null", and the compiler warns when you get it wrong.
By default the generator ignores all that and declares every string as string, which is a lie for any
nullable column and produces warnings in a project that has nullable reference types enabled.
Turning this on makes the generator tell the truth:
-
#nullable enableis written at the top of each generated file, so the setting works even if your project has not opted in globally. - A nullable column becomes
string?. - A non-nullable column stays
stringand is initialised= null!, which tells the compiler "EF will populate this, stop warning me". - Required navigation properties get
= null!for the same reason.
Product.ProductName is NOT NULL; Notes and the computed DisplayLabel are nullable.
// Product
public class Product
{
public int ProductId { get; set; } // ProductId (Primary key)
public string ProductName { get; set; } // ProductName (length: 100)
public decimal UnitPrice { get; set; } // UnitPrice
public string Notes { get; set; } // Notes
public int CategoryId { get; set; } // CategoryId
public string DisplayLabel { get; private set; } // DisplayLabel (length: 150)
// Foreign keys
/// <summary>
/// Parent Category pointed by [Product].([CategoryId]) (FK_Product_Category)
/// </summary>
public Category Category { get; set; } // FK_Product_Category
public Product()
{
UnitPrice = 0m;
}
} // Product
public class Product
{
public int ProductId { get; set; } // ProductId (Primary key)
public string ProductName { get; set; } = null!; // ProductName (length: 100)
public decimal UnitPrice { get; set; } // UnitPrice
public string? Notes { get; set; } // Notes
public int CategoryId { get; set; } // CategoryId
public string? DisplayLabel { get; private set; } // DisplayLabel (length: 150)
// Foreign keys
/// <summary>
/// Parent Category pointed by [Product].([CategoryId]) (FK_Product_Category)
/// </summary>
public Category Category { get; set; } = null!; // FK_Product_Category
public Product()
{
UnitPrice = 0m;
}
}Three changes: Notes and DisplayLabel became string?, and ProductName and the Category navigation
property gained = null!.
Turn it on if your project has <Nullable>enable</Nullable>. Otherwise the generated file produces a
warning for every non-nullable string property - "Non-nullable property must contain a non-null value when
exiting constructor" - and those warnings drown the ones you care about.
Leave it off for a project that has not adopted nullable reference types. string? in a file whose
project has the feature disabled is a compiler error, not a warning.
= null! is a promise, not a check. It says "trust me, this is populated". It is true when EF materialises
the entity and false when you write new Product() yourself, where ProductName really is null despite its
type. That is the standard EF Core compromise, not something this generator invents.
It changes value types too, not just strings, despite the name. Nullable columns of every type follow the
same rule, though int? was already how a nullable int was generated.
It interacts with Settings.NullableShortHand.
NullableShortHand chooses between int? and Nullable<int>; this chooses
whether reference types participate at all.
The generated file opts itself in. #nullable enable at the top means the file is nullable-aware even in
a project that is not. That is deliberate - it keeps the generated code consistent - but it can surprise you
when the generated file is the only one with the feature on.
Settings.NullableReverseNavigationProperties is separate. This setting handles required navigation
properties with = null!; that one decides whether one-to-one reverse navigations are declared nullable.
-
Settings.NullableShortHand -
int?versusNullable<int> - Settings.NullableReverseNavigationProperties
- Settings.UsePropertyInitialisers - the other setting that changes how properties are initialised
- Settings Reference
- Settings A-Z - every setting, with a page each
- Common Settings Types Explained
- Settings Callbacks
- Settings runtime values and helpers
- Filtering
- Full Control Over the Generated Code
- Enum Generation from Table Data
- Owned Entities
- JSON column support
- Global Query Filters
- Extended Property Names Feature
- Partial Properties
- File-Scoped Namespaces
- Data Annotations
- Spatial Types
- HierarchyId
- RowVersion and TimeStamp columns
- Lazy Loading
- Stored proc result sets
- Custom File-Based Templates
- Extra entities via partial classes
- INotifyPropertyChanged
- Syntax colour for T4