-
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
EF Core 1.0 not including columns with default values in insert into query #7089
Comments
I think we made some bug fixes around this in 1.1. Could you upgrade to 1.1 and see if the issue is fixed? https://blogs.msdn.microsoft.com/dotnet/2016/11/16/announcing-entity-framework-core-1-1/ |
I have upgraded to EF Core 1.1.0 and still have the issue |
@mdelprado-emphasys This looks like a dupe of #6054. If you need a bool with a store-generated default, then use a nullable bool. This gives EF a way to distinguish between not set (null) set to false and set to true. |
@ajcvickers do you think there is an opportunity here for a model validation error or warning? |
@divega Yes, I think that would be a good idea. |
@divega what kind of error or warning were you talking about? BTW, I'm not sure what exactly did people expect to happen with boolean with default value of true... Did they expect EF to change the C# / CLR spec? |
@gdoron we need to do more analysis but I think the warning would only apply to Boolean properties. When you specify that a property has a default value in the database, EF Core will use the default value of the CLR type as an indication that it should let the database set the default value, hence it won't include the column in the INSERT operation. But Boolean properties only have two states, so it is unlikely that you would intend any of these two values to mean "leave the column alone":
|
This is why I don't get what did they expect to happen, and they may expect a similar thing with numeric properties too, I assigned my property 0 but it's being ignored. |
@gdoron , @divega It makes sense, now that you mention, that if I don't have a nullable type, the EF just adds the default value, but I was actually expecting the same behavior than when I do an INSERT INTO directly in the database. The INSERT INTO just adds the record with the values I send in the query and ignores the default values. |
@mdelprado-emphasys That's because SQL doesn't have the limitation there actually is a property that being sent. |
IMO, when a property is not nullable, the |
@GertArnold It would be very annoying having DateTime? InsertDate all over the place just because people make mistakes. |
@gdoron I see your point. But people are going to tack |
There seems to be more useful information in this issue now than in the original #6054, so closing that one as a duplicate of this one. |
@GertArnold that is an interesting insight. I do agree that currently you need to understand a lot before you can make some of these scenarios work correctly. However as @AndriySvyryd pointed out in a recent conversation, Instead what we are looking at is to introduce a warning (on second thought, besides bool it should also probably apply to properties of enum types) which suggests making the property of a nullable type. If the property is nullable then the default value of the CLR type will be null, which is hopefully outside of the domain of values you intend to store in the database and hence a better choice of a "sentinel value" to indicate that the value will be generated in the store. In fact in most cases if you have We have considered other options, e.g.:
But these options seem to lead to a more complicated experience or mental model and not necessarily help as much as making the property of a nullable type. cc @ajcvickers |
@ajcvickers to split this out into some separate actionable items |
You are using .NET ORM and as such there are CLR limitations like this one. I honestly not sure what's so complicated about this concept. |
@gdoron the concept isn't complicated - it just causes very unexpected behavior which hurts programmers. Of course if people would read all the documentation and already know about this, it's logical why it happens, but that still doesn't remove the problem. Fact is, that people will not plan for this or assume it will happen, until in hits them unexpectedly. And that's bad. Basically part of the problem is simply that the insert wants to optimize for default values, resulting in an insert which is inconsistent with what the developer coded. That's very bad, and EF shouldn't do that. |
Suggest alternative. |
Here's a trivial alternative: |
I don't think you understood what I wrote about the CLR. This is becoming a lengthy and repetitive thread. |
@gdoron I understand, and I must admit I haven't read every single post here - because it is too long. Sorry about that. I often think git is missing a summary-feature at the beginning of the thread, where the admin could summarize the situation and everything. |
@Allann I'm saying you shouldn't use sentinel values to insert database defaults. I'm saying if you want (for legit reasons) to insert database defaults then either you do it by not mapping the columns in the model or with an explicit API. |
@Allann Your statement at the end, especially this part "using nullable properties (that remain null), the database takes over and supplies the default values" describes the behavior in EF Core. The EF6 code doesn't really work like this. EF6 either always uses the default constraint (with linitations) or never uses the default constraint. There is no way to have some inserts for that property use it, while others do not. (Note that EF Core can be configured to do the same thing using StoreGeneratedAlways.) From what I can tell, the nHibernate code works the same was as EF6--that is, it will always use the database constraint. If it doesn't, then it looks like it would work the same way as EF Core since there is no other information provided that could make it work otherwise. @popcatalin81 I don't think that is an unreasonable interpretation, and there is a way to set this up with EF Core using StoreGeneratedAlways. However, we have had a lot of feedback over the years indicating that many developers want the ability to insert only when an explicit value has not been set. |
@ajcvickers since NHibernate uses proxies it actually can know if Foo equals false because it was never set or because it was set to false. Maybe you can also define a new EF Boolean type (with implicit casting to Boolean), though I don't think it would be any easier and user friendly than what we have now. |
@gdoron I don't think the nHibernate code is using a proxy, or, if it is, it is created later and so wouldn't help here, because the code explicitly says I agree that the new Boolean type wouldn't be better than using a nullable bool. |
I think there are two different problems and mindsets at conflict here.
This is typical case where you'd want to use the database generate value. Example 2:
You'd really like to be able to insert null here as it is significant for the logic. Example 3:
You'd really want to be able to insert false here even if for some other reasons you had to choose the default to be true. What I'm trying to say, database defaults diffent from NULL and the need to insert NULL are common but EF core makes this scenario (and others) somewhat difficult. |
@popcatalin81 Agreed that being able to sometimes insert null for a given property, but sometimes have the value be store-generated for the same property is something EF Core can't do. We explicitly scoped that out some time ago. This is the first time I have heard someone ask for it. 😸 The other cases are all doable in various ways--using nullable properties or StoreGeneratedAlways. |
I always was an early adopter, and used newest EF versions even in brown fields (dating back to EF 1 Beta 1 days ....) Just wait for it ... 😄 |
I totally don't get why this could be an issue. let |
Just want to weigh in as this issue has just stung us. Unsure why it has been closed. Completely unexpected behaviour that this would make it impossible to set false when inserting a record. |
Using V5.0.5 and this is still an issue. |
We also ran into this issue. After finding this issue here, knowing that this is not a bug but a feature, i checked for all our default constraints. I am wondering about a few things:
We make use of database first and rescaffold our database on every database update. If 2. is to complex, how about wrapping some of the complexity. How about a type //lets assume Article.SalesPrice and Article.IsInStock got a default constraint that differs from CLR-default.
//example 1
var tracker = dbContext.ChangeTracker.New<Article>();
tracker.Set(nameof(Article.Name), "Shirt");
tracker.Set(nameof(Article.SalesPrice), 0.0m);
tracker.Set(nameof(Article.IsInStock), false);
dbContext.SaveChanges();
var entity = tracker.GetEntity(); //or .GetInstance()
//do some other work with entity.
//example 2
var entity2 = new Article() { Name = "Hat" };
var tracker2 = dbContext.ChangeTracker.Track(entity2);
tracker2.Set(nameof(Article.SalesPrice), 0.0m);
tracker2.Set(nameof(Article.IsInStock), false);
dbContext.SaveChanges();
//do some other work with entity2 I derived this idea from OData, which is offering a |
Version 6.0.9 + Sql Server 15.0.2000.5 = error too
How about check collunm setted and != SQL DefaultValue ? Now i'm need check all default values in my project and check all functions(400+) have insert new rows correct to db Sorry but - its fail!! |
Steps to reproduce
I'm using EF Core 1.0 and I have a model where I design some properties with default values similar to
modelBuilder.Entity<Listings>(entity => { entity.Property(e => e.IsActive).HasDefaultValueSql("1");}
The table in the database is created correctly defining the columns with the corresponding default value
[IsActive] bit NOT NULL DEFAULT 1
The issue
When I add a new entity and save changes in my context, the insert into statement generated does not contain the properties that have default values even though I assign specific values for those properties. The result in the database is a record where the columns with default values doesn't contain the values I passed in my model.
More info on this post
http://stackoverflow.com/questions/40619319/entity-framework-not-including-columns-with-default-value-in-insert-into-query/
Further technical details
EF Core version: 1.0
Visual Studio version: VS 2015
The text was updated successfully, but these errors were encountered: