-
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
Uniquify and validate Check Constraint name #18958
Comments
Alternatively, rather than differentiating the behavior between |
Note for triage: we should do a review of the CheckConstraint code. Looks like the design could be lacking in a few areas. Looking at the PR it seems like a couple of people did review it, but we still missed things; we should discuss in the retrospective. |
My current solution to this is a custom convention, if anyone is interested: public sealed class ScopedCheckConstraintNameConvention : IModelFinalizedConvention
{
public void ProcessModelFinalized(IConventionModelBuilder modelBuilder, IConventionContext<IConventionModelBuilder> context)
{
foreach (var entityType in modelBuilder.Metadata.GetEntityTypes())
{
foreach (var checkConstraint in entityType.GetCheckConstraints().ToList())
{
var newName = FormattableString.Invariant($"CK_{entityType.GetTableName()}_{checkConstraint.Name}");
entityType.RemoveCheckConstraint(checkConstraint.Name);
entityType.AddCheckConstraint(newName, checkConstraint.Sql);
}
}
}
} This is better than the extension method because if you set the table name after calling the extension method, it would still use the old table name. |
I tried hard but couldn't find a single piece of documentation about constraint naming on SqlServer. It always talks about naming rules but not the scope. Based on empirical testing data,
Type1 needs to have unique name across database. PK on blog table with same name as AK on post table also fails.
We have validation to see if PK/AK/FK/Index names are unique in given table also accounting for table sharing.
|
In SqlServer, Type1 names need to be unique across a schema not the entire database, the code below runs fine.
Supporting documentation - https://docs.microsoft.com/en-us/sql/t-sql/statements/create-table-transact-sql
|
Removing from backlog to discuss what to do here for the plugin verses manually written calls to |
Notes from team discussion:
|
If you plan to add an overload to HasCheckConstraint that doesn't take a name, it would be great if you could also add an overload to HasDefaultValue that does take a name to align the two. |
Allow to specify check constraint store name independently of the model name. Ensure check constraint model is unique across the hierarchy. Remove check constraints from the runtime model. Fixes #18958
Allow to specify check constraint store name independently of the model name. Ensure check constraint model is unique across the hierarchy. Remove check constraints from the runtime model. Fixes #18958
Allow to specify check constraint store name independently of the model name. Ensure check constraint model is unique across the hierarchy. Remove check constraints from the runtime model. Fixes #18958
Allow to specify check constraint store name independently of the model name. Ensure check constraint model name is unique across the hierarchy. Remove check constraints from the runtime model. Fixes #18958
For reference, SQL Server and MySQL require check constraints to be unique across tables, while PostgreSQL and Sqlite do not. @AndriySvyryd if it's not too hard, we could allow providers to specify whether uniquification is needed, what do you think? Though I agree the extra table name in the CK name isn't a big problem. |
Great, thanks! |
Great - all further migrations broken from that point 👎 - trying to drop existing constraints by a name which they never have got in the past. |
https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-6.0/breaking-changes#unique-check-constraints outlines how to mitigate the breaking change |
I'm sorry @ryan-carbon but the mitigation shown there doesn't help / is not what I want. The new unique names are a good thing and I for sure want them for all new stuff or any constraints I modify. So I finally changed the name parameter of |
@springy76 We reverted a part of the breaking change in #27142, it will be shipped in 6.0.2 Let us know if you are still experiencing the issue after the patch |
HasCheckConstraint
has aname
parameter that it uses as the name of the constraint in the database.Constraints are database objects and their names must be unique in the whole database (not just the table they belong to... as I found out the hard way by getting into a conflict 😄), so to mitigate this we should a use naming convention. Right now we have to do this manually and prepend our constraint names with the name of the table like this:
That's why I created an extension method that does this for me:
and also uses the standard
CK
prefix as a convention. Then I only useHasLocalCheckConstraint
to create check constraints and have to be careful to never callHasCheckConstraint
directly.It would be nice if EF Core had this feature builtin or could do this automatically. It would also ensure that all database object created by EF Core follow the naming convention that it uses now, with a two letter prefix for the type of the object (such as
PK
,AK
,FK
,IX
).Just changing the existing behavior of
HasCheckConstraint
would of course be a huge breaking change and adding a parameter to opt-in to this behavior would be clumsy and it should really be the default in my opinion.I also noticed that while methods like
HasDefaultValue
,HasDefaultValueSql
andHasComputedColumnSql
follow the convention where if they take SQL, their names end withSql
, and if there's an expression-based version, it doesn't. What if the existing method was deprecated and the new name would beHasCheckConstraintSql
with this new naming behavior? If there's an expression-based version added later (#15409), that would take the nameHasCheckConstraint
and still follow the new behavior because it would be a separate overload from the deprecated one (or the deprecated one could be gone by that time).To allow for compatibility with existing constraint names, the new method could take an optional parameter (bool or enum) to disable the name transformation, but it should be on by default in my opinion.
The text was updated successfully, but these errors were encountered: