-
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
Reverse engineering: Scaffold-DbContext can generate IsRequired() on nullable unique column if it is also an FK #7956
Comments
If I set like this There is no IsRequired() added. It looks weird. It should be the other way around. |
What is the value of the "nullable" column for that table/column when you run this: |
Hi @ErikEJ What do you mean. How can I run what you mean in your link? |
In SQL Server management studio against your database |
Name column nullable value = 1 in SSMS |
So it is currently ?
|
Yes, exactly |
Did you find anything @ErikEJ ? |
We discussed this in triage and decided that we should reverse engineer what the schema says even if it is not something we would generate by default. We should also look at whether or not this should generate warnings in model validation. |
Hi @ajcvickers . Yes the flow should be reversed with SQL schema. Column allow null then it generated IsRequired(), Column "not null" then there was no IsRequired() specification. For now after scaffolding I have to change DbContext file manually to make EF querying correctly. Thanks |
Note: this doesn't happen if you don't create the index; then What's going on here is that in RelationalScaffoldingModelFactory.VisitIndex() the scaffolder is correctly calling Need to have a look at that code and maybe allow a new API |
@lajones Just because there is a unique index does not mean that there should be an alternate key. There should only be an alternate key if the the properties are at the principal end of a foreign key constraint. |
OK. Then we should be calling |
I've been looking at this offline. It's OK to not call If the index is just a separate independent (i.e. not supporting an FK) index then this causes no problems. But if the index is on the principal end of an FK (and includes a nullable column) then we see an exception from the Scaffolder:
This is because the Scaffolder tries to add an alternate key on the Entity where the principal end of the FK is located and the property has been set up as nullable (previously it wasn't nullable because the index, through the Options:
In all cases I think we should log a warning from the Scaffolder saying it has encountered the situation. For options 2 and 3 we should consider also warning in model validation. @ajcvickers - you asked what Scaffolding would do if it came across a primary key column which is nullable. Firstly, this is not possible to set up in a SQL database as of SQL-92 (and maybe earlier) - the |
OK. Will go ahead with that. @sonphnt - the effect this will have is that the property |
@ajcvickers @lajones FWIW, nullable alternate keys (i.e. nullable columns in a unique constraint) are legal in the SQL standard and seems to be supported in at least some databases. Even in SQL Server it is legal, although the behavior does not adhere to the standard in the sense that NULLs values are not completely ignored. The idea is something like "I sometimes don't know the value of this column, but when I do, it uniquely identifies the row". My 👍 is because I agree it should be ok to restrict properties in alternate keys to be required in EF Core unless or until we have evidence that it is important to customers to remove this restriction (I am assuming this is what we have right now, and it would be somewhat expensive to change it, but I wanted you to keep this in mind). |
@divega @ajcvickers Please don't force IsRequired on nullable unique columns. I can give a clear example where this would create a blocking issue for the app I'm working on. There is an Users table with (ID pk, UserName NOT NULL Unique, EMail NULL Unique). In this design the email is optional but also required to be unique. Also null in the email column is used to drive different business processes (IE: different password reset process) and String Empty won't work (due to uniqueness constraint) and filling in random unique values to please EF would be a terrible workaround. |
@popcatalin81 I agree. There are some cases we need nullable unique columns in business logic. Somethings like Either we dont have a value but if it does, it should be unique. Your example has reflected exactly a business logic in enterprise application I think nullable unique columns is legal point in SQL standard. If not Microsoft SQL server should not allow users creating unique index like that in database. @lajones The second option, what does it mean? I dont get it. My example is on Name property column but we can have a foreign key id. By making this column nullable unique that will make the column become a "one-zero,one" relationship. And second thing Required() on a column that will make EF generate a query with INNER JOIN between 2 tables base on that Required column. We expect a "LEFT JOIN" here in this scenario due to Nullable unique column. One of many examples between 2 tables about that: If we do not set Nullable unique column on SecurityCardId
The associate/parttime employees do not have SecurityCardId. but an official employee of company will have one security card and the card must be unique for everyone. |
@sonphnt @popcatalin81 We are not intending to disallow nullable unique columns. Nor is it about nullable unique columns that are part of a foreign key. The conversation in the recent posts is only about cases where there is a foreign key constraint where the constraint references columns that are not the primary key. Example:
FK constraint from OwnerBlogName on Post (the FK) to BlogName on Blog (not the PK) In this case EF cannot handle nulls in BlogName on Blog. Nulls in the OwnerBlogName (the FK) on Post are allowed. @divega The state manager treats PKs and alternate keys in the same way--no nulls and values cannot be changed. Both of these restrictions could be relaxed. We just haven't done the work to do it. Also, we would have to understand the meaning of null, but if it just means that no FK will ever match it, then that should be fine and not difficult to implement. |
@sonphnt @popcatalin81 As @ajcvickers says above - it is only nullable, unique columns on the prinicipal end of the FK that are affected. Nullable, unique columns on the dependent end are perfectly normal and are unaffected by the plan above. Both of your situations are describing the dependent end. |
Fixed by PR #8089. |
@ajcvickers Good to know. I see relaxing those two restrictions (nullability and mutability) on alternate keys as orthogonal improvements. And yes, I believe a null alternate key value could not participate in relationships. I tested it in SQL Server and null values on the principal and dependent keys do not form a relationship. Do you think it is worth creating an issue for this? |
@divega Yes. We should have issues for both relaxations, although we might have one for the mutability already on the backlog. |
@ajcvickers FYI, nullability is already covered in #4415 and mutability in #4073. |
Hi Everyone,
I have a column with unique index like this.
The class generated by Scaffolding look like this
Why it added IsRequired() into Name property?
Is it a bug? And is it possible to do a unique nullable column in Entity Framework?
Thanks
The text was updated successfully, but these errors were encountered: