我使用的是EF Core 1.1.0,但是我遇到了严重的级联行为问题。
我有一个名为Land的模型如下:
public class Land
{
public long Id { get; set; }
public int HorizontalPosition { get; set; }
public int VerticalPosition { get; set; }
public bool IsPlaced { get; set; }
// Relations
public string UserId { get; set; }
public virtual User User { get; set; }
public long? BuildingId { get; set; }
public virtual Building Building { get; set; }
}
和另一个名为Building的模型如下:
public class Building
{
public long Id { get; set; }
public bool IsPermanent { get; set; }
public int UpgradeCount { get; set; }
// Relations
public string UserId { get; set; }
public virtual User User { get; set; }
public int BuildingTypeId { get; set; }
public virtual BuildingType BuildingType { get; set; }
public virtual List<Land> Lands { get; set; }
}
在dbcontext中我提到了一个关系:
...
modelBuilder.Entity<Land>()
.HasOne(l => l.Building)
.WithMany(b => b.Lands)
.HasForeignKey(l => l.BuildingId)
.OnDelete(Microsoft.EntityFrameworkCore.Metadata.DeleteBehavior.SetNull);
...
但是当我尝试更新数据库时,我收到此错误:
System.Data.SqlClient.SqlException: Introducing FOREIGN KEY constraint 'FK_Lands_Buildings_BuildingId' on table 'Lands' 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.
at System.Data.SqlClient.SqlConnection.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.Internal.MigrationCommandExecutor.ExecuteNonQuery(IEnumerable`1 migrationCommands, IRelationalConnection connection)
at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.Migrate(String targetMigration)
at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.UpdateDatabase(String targetMigration, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabase.<>c__DisplayClass0_1.<.ctor>b__0()
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
ClientConnectionId:65b8e08e-2d17-46ac-b734-385f88dd07b1
Error Number:1785,State:0,Class:16
Introducing FOREIGN KEY constraint 'FK_Lands_Buildings_BuildingId' on table 'Lands' 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.
生成的迁移是这样的:
...
migrationBuilder.AddForeignKey(
name: "FK_Lands_Buildings_BuildingId",
table: "Lands",
column: "BuildingId",
principalTable: "Buildings",
principalColumn: "Id",
onDelete: ReferentialAction.SetNull);
...
我已经告诉过,在删除时将外键设置为null但是它要我不做任何操作。虽然在dbcontext中没有名为NoAction&#39;!
的行为答案 0 :(得分:1)
在EF Core 2.2.6版中,ClientSetNull
枚举中有一个Microsoft.EntityFrameworkCore.DeleteBehavior
条目。
在我的情况下,使用ClientSetNull
代替SetNull
有所不同。
我不明白为什么MsSqlServer无法解析多个级联路径,而其他引擎完全可以解析。
答案 1 :(得分:0)
您看到的异常文本是由SQL Server生成的。
EF Core没有任何等效的NO ACTION
。
您唯一的方法是将Restrict
设置为一个参考(或两者)。
在删除父实体(Lands
)之前,您需要手动管理相关记录(例如,更新或删除User
)。或者,在渲染视图时检查子记录是否存在,并且不显示用于删除用户的链接/按钮。或者在删除,中止操作期间捕获异常并向用户显示相关消息。