-
Notifications
You must be signed in to change notification settings - Fork 226
Settings.NullableShortHand
Two small settings about nullability that are easy to confuse with each other and with Settings.AllowNullStrings.
Settings.NullableShortHand |
Settings.NullableReverseNavigationProperties |
|
| Type | bool |
bool |
| Default | true |
false |
| Affects | How a nullable value type is spelled | Whether a one-to-one reverse navigation is nullable |
In Database.tt? |
Yes | Yes |
Pure syntax. true gives int?; false gives Nullable<int>.
Document.ReviewedByUserId is a nullable int.
// Document
public class Document
{
public int DocumentId { get; set; } // DocumentId (Primary key)
/// <summary>
/// The title shown to users. Not the file name.
/// </summary>
public string Title { get; set; } // Title (length: 100)
public byte[] RowVersion { get; set; } // RowVersion (length: 8)
public int? ReviewedByUserId { get; set; } // ReviewedByUserId
} // Document
public class Document
{
public int DocumentId { get; set; } // DocumentId (Primary key)
/// <summary>
/// The title shown to users. Not the file name.
/// </summary>
public string Title { get; set; } // Title (length: 100)
public byte[] RowVersion { get; set; } // RowVersion (length: 8)
public System.Nullable<int> ReviewedByUserId { get; set; } // ReviewedByUserId
}The two are the same type. The compiler treats int? as an alias for Nullable<int>, so this changes nothing
but readability.
Leave it true. int? is idiomatic C# and has been since 2005. false exists for code style rules that
demand explicit types, and for generators feeding tools that cannot parse the shorthand.
A modelling decision, not a syntax one.
In a one-to-one relationship the generator has to decide whether the parent's reference to the child may
be null. Person has one Passport - but does every person have one?
false (the default) generates public Passport Passport { get; set; }, saying the child always exists.
true generates public Passport? Passport { get; set; }, saying it might not.
true is usually the more honest answer: a one-to-one is normally optional on the parent end, because the
child row holds the foreign key and can simply be absent.
It only affects one-to-one relationships. A one-to-many parent gets a collection, which is empty rather than null, and a child's reference to its parent follows the foreign key's own nullability.
| I want | Setting |
|---|---|
int? rather than Nullable<int>
|
NullableShortHand = true |
string? for nullable string columns, and #nullable enable
|
AllowNullStrings = true |
Passport? on the parent of a one-to-one |
NullableReverseNavigationProperties = true |
They are independent, and in a project with nullable reference types enabled you probably want all three.
NullableReverseNavigationProperties = true emits ? on a reference type, which is a compiler error in a
project that has not enabled nullable reference types. Turn on
Settings.AllowNullStrings alongside it - that is what writes #nullable enable
into the generated file.
NullableShortHand has no effect on reference types. string has no shorthand to choose.
Neither changes the database mapping. IsRequired(false) in the configuration comes from the column's own
nullability, whatever these are set to.
Both are all-or-nothing. For per-relationship control, use
Settings.UpdateColumn and assign column.PropertyType.
- Settings.AllowNullStrings - the one that matters most in a nullable-aware project
- Settings.UpdateColumn - overriding a single property's type
- Settings.ForeignKeyFilterFunc - removing reverse navigations altogether
- 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