Using ABP Suite CRUD Generator, I have a model with navigation properties like so:
This produces in the DbContextModelCreatingExtensions.cs the following output:
builder.Entity<MyModel>(b =>
{
...
// optional foreign keys have DeleteBehavior.SetNull which is normally fine except when you have them pointed to the same target table multiple times like so:
b.HasOne<Grade>().WithMany().HasForeignKey(x => x.DefaultShapesGradeId).OnDelete(DeleteBehavior.SetNull);
b.HasOne<Grade>().WithMany().HasForeignKey(x => x.DefaultPlatesGradeId).OnDelete(DeleteBehavior.SetNull);
b.HasOne<Grade>().WithMany().HasForeignKey(x => x.DefaultTubesGradeId).OnDelete(DeleteBehavior.SetNull);
b.HasOne<Grade>().WithMany().HasForeignKey(x => x.DefaultBoltsGradeId).OnDelete(DeleteBehavior.SetNull);
...
// required foreign keys have DeleteBehavior.NoAction:
b.HasOne<ContractStatus>().WithMany().IsRequired().HasForeignKey(x => x.ContractStatusId).OnDelete(DeleteBehavior.NoAction);
});
The EF Core migrations script produced though is invalid with the following error due to the fact that the Grade table is being referred in multiple FK references:
Microsoft.Data.SqlClient.SqlException (0x80131904): Introducing FOREIGN KEY constraint 'FK_AppMyModels_AppGrade_DefaultPlatesGradeId' on table 'AppMyModels' 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.
The only way to fix this is to have the DeleteBehavior.NoAction
instead of SetNull
on the 4 foreign keys to the Grade table in the above example. Changing this manually in the above file isn't ideal as it gets overwritten whenever we make a change to the model via the CRUD Generator. Is there another way to change it?
Couple things I tried:
-
I also looked at Entity Extensions but it doesn't seem to be applicable here when adjusting existing FK.
-
Furthermore, manually overriding the configuration in the DbContext.cs file doesn't seem to have an effect either e.g.
public class CoreDbContext : AbpDbContext<CoreDbContext>, ICoreDbContext
{
...
protected override void OnModelCreating(ModelBuilder builder) {
base.OnModelCreating(builder);
builder.ConfigureCore();
// This has no effect on overriding the OnDelete behavior:
builder.Entity<MyModel>(b =>
{
b.HasOne<Grade>().WithMany().HasForeignKey(x => x.DefaultShapesGradeId).OnDelete(DeleteBehavior.NoAction);
b.HasOne<Grade>().WithMany().HasForeignKey(x => x.DefaultPlatesGradeId).OnDelete(DeleteBehavior.NoAction);
b.HasOne<Grade>().WithMany().HasForeignKey(x => x.DefaultTubesGradeId).OnDelete(DeleteBehavior.NoAction);
b.HasOne<Grade>().WithMany().HasForeignKey(x => x.DefaultBoltsGradeId).OnDelete(DeleteBehavior.NoAction);
});
}
}
The only way that seems to also work is setting the navigation property as Required which then produces the line with DeleteBehavior.NoAction
.
4 Answer(s)
-
0
Hello,
You can update the Suite's templates for this. See: https://abp.io/docs/latest/suite/editing-templates
-
0
It would be awesome to add more descriptions to the template box. So we can Identify which exactly is changing (maybe a screenshot with an info icon?)
-
0
Thanks, that should do the trick. I had an idea that customizing one of the templates would be necessary but for some reason I couldn't seem to isolate which one to edit.
-
0
Thanks, that should do the trick. I had an idea that customizing one of the templates would be necessary but for some reason I couldn't seem to isolate which one to edit.
Yes, this is one thing that we should enhance. It's hard to find the templates, I've created an internal issue for that.