-
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
Model Builder: Avoid foreign key cycles #6956
Comments
This is a SQL Server limitation in how it handles multiple cascade relationships. We don't try to compensate for this automatically because a) not all databases have this limitation and b) there are two main ways to deal with it and the choice of which to do should be made explicitly:
|
Thanks for the info. This is an issue in two class hierarchies in my domain model. I plan to map both as TPT (#2266) or TPC (#3170) once the alternative is available. Am I correct that, in the above example, this issue will disappear when I move If "yes" then I'd conjecture that the correlation between this issue and alternative mapping strategies isn't limited to the above example or my domain model. The larger the class hierarchy, the more likely those derived classes reference each other; also the more reason to use an alternative mapping strategy. At least those seem true in my case. The alternative mapping strategies are on the back burner, so I'm stuck with one of the hacks suggested above for now. For short-term development needs, I can turn off the cascade delete behavior. As I implement more functionality, however, accommodating this workaround will become more cumbersome. |
@HappyNomad Maybe file an issue on SQL Server to be less restrictive in what they report as a "cycle"? |
@ajcvickers The issue was already filed: Foreign key that references the same table. It's "Active" but it's been around since 2009. Since adding TPT to EF-Core would solve the issue in my case, I hope it doesn't stagnate too. Triggers are mentioned as another workaround. Could this be incorporated into EF-Core's SQL Server provider? At least the hacky stuff would be taken out of user code. |
We discussed this but decided we don't want to work around this limitation in the EF stack. |
It feels to me like this SQL Server specificity could be handled similarly to others in SqlServerModelBuilderExtensions |
The issue can be reproduced with this version:
and this context:
and this model:
The exception is:
System.Data.SqlClient.SqlException was unhandled by user code
Class=16
HResult=-2146232060
LineNumber=1
Message=Introducing FOREIGN KEY constraint 'FK_PBase_PBase_PreID' on table 'PBase' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Could not create constraint or index. See previous errors.
Number=1785
Procedure=""
Server=(localdb)\mssqllocaldb
Source=Core .Net SqlClient Data Provider
State=0
StackTrace:
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action
1 wrapCloseInAction) at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action
1 wrapCloseInAction)at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
at System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean async, Int32 timeout, Boolean asyncWrite)
at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource
1 completion, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite, String methodName) at System.Data.SqlClient.SqlCommand.ExecuteNonQuery() at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.Execute(IRelationalConnection connection, String executeMethod, IReadOnlyDictionary
2 parameterValues, Boolean closeConnection)at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteNonQuery(IRelationalConnection connection, IReadOnlyDictionary
2 parameterValues) at Microsoft.EntityFrameworkCore.Migrations.MigrationCommand.ExecuteNonQuery(IRelationalConnection connection, IReadOnlyDictionary
2 parameterValues)at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationCommandExecutor.ExecuteNonQuery(IEnumerable`1 migrationCommands, IRelationalConnection connection)
at Microsoft.EntityFrameworkCore.Storage.RelationalDatabaseCreator.CreateTables()
at Microsoft.EntityFrameworkCore.Storage.RelationalDatabaseCreator.EnsureCreated()
at Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade.EnsureCreated()
at EFGetStarted.AspNetCore.NewDb.Startup.Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, BloggingContext dataContext) in C:\Users\Adrian\Development\Examples\ASP.NET Core\EFGetStarted.AspNetCore.NewDb\src\EFGetStarted.AspNetCore.NewDb\Startup.cs:line 56
InnerException:
The text was updated successfully, but these errors were encountered: