Reverse engineering a non-nullable bit column with DEFAULT constraint incorrectly generates nullable value type (i.e., bool? rather than bool)
See original GitHub issueA bit NULL
column correctly generates a property typed as bool
.
A bit NOT NULL
column correctly generates a property typed as bool?
.
A bit DEFAULT ((1)) NOT NULL
column incorrectly generates a property typed as bool?
.
If a non-nullable bit column has a DEFAULT value, then it should generate the non-nullable value type bool
, not bool?
.
This is wreaking havoc with our codebase, where developers are adding undesirable and error-prone code, such as needlessly testing .HasValue
, and/or adding needless coalesce (i.e., if (x.IsActive ?? false)
rather than if (x.IsActive)
.
Provide steps to reproduce
Create a table with three bit columns; for example:
CREATE TABLE MyTable (
NB bit NULL,
NNB bit NOT NULL,
NNBD bit DEFAULT (1) NOT NULL)
Then reverse-engineer the table and notice the generated code:
public bool? NB { get; set; }
<- correct
public bool NNB { get; set; }
<- correct
public bool? NNBD { get; set; }
<- incorrect, should be bool
See image below.
Provide technical details
-
EF Core version in use: 3.1.4
-
Is Handlebars used: I think so (not sure what this means, but
Customize code using Handlebars templates C#
is checked). -
Is .dacpac used: I think so (the generator source is a
.sqlproj
project, not the actual database). However, I have confirmed that this issue occurs whether generating from the.sqlproj
project or the actual database). -
EF Core Power Tools version: 2.5.1020.0
-
Database engine: SQL Server 2019
-
Visual Studio version: Visual Studio 2022
Issue Analytics
- State:
- Created a year ago
- Comments:9 (5 by maintainers)
Top GitHub Comments
EF uses the CLR default (false) to determine that a value hasn’t been set by the user.
If a value hasn’t been set, and the property has a default constraint EF won’t send the value to the database so the DEFAULT constraint will be used.
Since the default value is 1, that value is propagated back to the objects after calling
SaveChanges
. Hence, whether you specifyfalse
ortrue
, the result is alwaystrue
.Introducing a nullable
bool
helps EF differentiate between the two calls above and allows you to insert bothtrue
andfalse
.LOL - You should ask the EF Core team for a more explicit explanation!