-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Re-consider how default values are reverse engineered #9627
Comments
Triage: we will update reverse engineering to not make the property store-generated if the default value from the column matches the default value of the CLR property. |
This change break with the model, if you need to use the default value in a entity, the logical is set these in the constructor of the class or in the property how default value. The problem is when the database modify the record after insert with a trigger, calculate fields, another procedure or function of transact-Sql that EF don´t know. For example if your default value is a function in sql server how In my opinion the use of default values should be something like this:
// Or using default values in properties
|
Can you guys just hotfix this nullable bool scaffold behavior instead of shipping on 2.1.0? Maybe ship a 2.0.1? Just add a quick flag when invoking the command line scaffold tool or something perhaps, please? Currently my workaround is to downgrade the separate project containing the DbContext class + entity classes + the EF Core + its I mean, 2.1.0 / Q1 2018 is a pretty long wait... EDIT: ErikEJ's Toolbox is very cool. Love it. But I still prefer my black and white console: |
@ryanelian you can use my SQLite Toolbox to generate the v1 scaffolding, without installing anything in your solution 😀 - also works for SQL Server |
Triage: we plan to make the following change in 2.0.1: for non-nullable bool columns in SQL Server that have a column default of false, we will scaffold a non-nullable bool property without any store generation flags. Post 2.0.1 we will do what is described in the triage comment above. We will not change the behavior where the default in the database is not the CLR default. Specifically, for bool columns that have a default of true, we will still scaffold a nullable bool. This is because non-nullable bool properties with a store-generated value of true are not useful--the value in the database will always be true--see #8400 and #7163 for more details. |
@JuanIrigoyen This is the scenario I am talking about. Entity with a non-nullable bool: public class Fooo
{
public int Id { get; set; }
public bool Flag { get; set; }
} Configured in EF to have a store-generated default of true: modelBuilder
.Entity<Fooo>()
.Property(e => e.Flag)
.HasDefaultValueSql("(1)"); With this configuration, Flag will always be saved as true; never false, and hence is not useful. For example: using (var context = new TestContext())
{
context.Database.EnsureDeleted();
context.Database.EnsureCreated();
context.Add(new Fooo { Flag = false });
context.SaveChanges();
}
using (var context = new TestContext())
{
Debug.Assert(context.Fooos.First().Flag);
} This behavior hasn't changed from EF Core 1.0--there's lots of discussion in the linked issues that talk about this. The most complete is probably in #7089. Essentially, the issue is that the sentinel to tell EF to use use a store-generated value is the same as the value 'false'. The ways to make this work are:
|
I can't understand. This is my table: CREATE TABLE Employee
(
EmployeeId VARCHAR(64) CONSTRAINT PK_Employee PRIMARY KEY,
Username VARCHAR(256) CONSTRAINT UQ_Employee_Username UNIQUE NOT NULL,
Password VARCHAR(256),
PasswordUpdatedAt DATETIME2,
Name VARCHAR(256) NOT NULL,
Email VARCHAR(256),
IsEnabled BIT NOT NULL DEFAULT 1,
) This is from EF Core 1.1.2 scaffold (navigation properties and some stuffs are omitted for brevity): public partial class Employee
{
[Column(TypeName = "varchar(64)")]
public string EmployeeId { get; set; }
[Required]
[Column(TypeName = "varchar(256)")]
public string Username { get; set; }
[Column(TypeName = "varchar(256)")]
public string Password { get; set; }
public DateTime? PasswordUpdatedAt { get; set; }
[Required]
[Column(TypeName = "varchar(256)")]
public string Name { get; set; }
[Column(TypeName = "varchar(256)")]
public string Email { get; set; }
public bool IsEnabled { get; set; }
} public partial class MyDbContext : DbContext
{
public virtual DbSet<Employee> Employee { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Employee>(entity =>
{
entity.HasIndex(e => e.Username)
.HasName("UQ_Employee_Username")
.IsUnique();
entity.Property(e => e.IsEnabled).HasDefaultValueSql("1");
});
}
} This is the C# code for setting e.IsEnabled = form.IsEnabled;
await DB.SaveChangesAsync(); The field is very clearly set to
Please help me understand this phenomenon. |
@ryanelian It can be updated to false, but never inserted as false. |
Ahh. That explains it. Perhaps to maintain compatibility with database context created with version 1 scaffold, public partial class Employee
{
public bool IsEnabled { get; set; } = true; // or false
} i.e. For now, no need to implement that for each and every data type. Just make an compatibility flag to scaffold boolean property like that, please? That way you won't break compat for 2.0.0 and 1.X.X users... |
Hi @ryanelian. We are gathering information on the use of EF Core pre-release builds. You reported this issue shortly after the release of 2.0.0 RTM. It would be really helpful if you could let us know:
Thanks in advance for any feedback. Hopefully this will help us to increase the value of pre-release builds going forward. |
Yes
When I installed 2.0.0 preview1 SDK on my machine, I was not able to compile my 1.1.X project from Visual Studio 2017 Update 2 even when So I stopped playing with pre-release builds...
Don't break Visual Studio 😕 |
Impact: Refer to first post. |
Note from triage: post 2.1 we should consider adding a flag that will cause reverse engineering to ignore column defaults when defining the EF model. However, some thought needs to go into how this would interact with update-from-database. Leaving it up to @bricelam to decide how to track this--using an existing issue or creating a new one. |
Filed #10881 (Option to ignore DEFAULT constraints) |
Notes from implementing this:
Both these classes will now be ignored by Reverse Engineering. 🎉 |
@bricelam Are the default values generated by scaffolding used by EF anywhere? |
By reverse engineering |
So the actual value only really matters for round-tripping, but since we have to put something... |
OK, so it is used by the Update pipeline - thanks! I will add them, then: And what about sequences in the Model? |
Sequences, constraint names, non-unique indexes, and index filters aren't currently used by the runtime and are mostly there for round-tripping. |
I ran in to this today too. I was wanting to set a default value with my code first DB generation, so that the column would end up with XXX bit NOT NULL DEFAULT 0 |
You can either wait for the version that it is fixed or use the ignore when creating the connection in startup. Pretty sure there was an example above. |
I thought the newer versions were going to fix the need for BoolWithDefaultWarning on bool properties within a model. |
@cgountanis That warning should not be generated when reverse engineering with the 2.1 tools. Can you please create a new issue describing specifically when you are seeing this? Please include the column definition and the generated code. |
Feedback on 2.0 (e.g. #9507 #9617) has made me think about what the real intent is behind having columns with default values. Specifically, I think it is likely wrong to assume that the EF model should have a store-generated property just because there is some default on the column. It may well be the cause the the application will always supply a value and so, when using EF, the default is never used. The default may instead be there because:
Going beyond the most general case, if the CLR default would generate the same value as the database default, then having EF do store generation is a no-op anyway. If an app was relying on this for bools in 1.1, and we now generate nullable bools, everything will still work, but the app needs to be updated to use nullable bools.
The text was updated successfully, but these errors were encountered: