简体   繁体   中英

Multiple DataAnnotation ForeignKeys cycles or multiple cascade paths Exception

I'm trying to understand and trust in EF. I have a database with tables and I'm trying to replicate most of the structure with EF Code-First technology as an exercise to practice their basics.

All my classes have 'Hb' as a prefix in their names. I want to write the object references on other classes without the 'Hb' on the property name.

I'm follow instructions of this site

The first implementation cause exceptions like:

Introducing FOREIGN KEY constraint 'FK_Common.HbZipcode_Common.HbCountry_CountryId' on table 'HbZipcode' 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.

[Required, ForeignKey("Country")]
public int CountryId { get; set; }
public virtual HbCountry Country { get; set; }

[Required, ForeignKey("State")]
public int StateId { get; set; }
public virtual HbState State { get; set; }

[Required, ForeignKey("City")]
public int CityId { get; set; }
public virtual HbCity City { get; set; }

// This Foreignkey never throw exception
[ForeignKey("Neighborhood")]
public int? NeighborhoodId { get; set; }
public virtual HbNeighborhood Neighborhood { get; set; }

I'm doing something wrong and I cannot see.
If anyone could help me it would be nice.

Edit:

After applying the solution passed by the plushpuffin , everything went as expected.
Here's the code:

var modelConfig = dbModelBuilder.Entity<HbZipcode>();
modelConfig
    .HasRequired(zc => zc.Country)
    .WithMany(c => c.Zipcodes)
    .HasForeignKey(zc => zc.CountryId)
    .WillCascadeOnDelete(false);

modelConfig
    .HasRequired(zc => zc.State)
    .WithMany(s => s.Zipcodes)
    .HasForeignKey(zc => zc.StateId)
    .WillCascadeOnDelete(false);

modelConfig
    .HasOptional(zc => zc.Neighborhood)
    .WithMany(n => n.Zipcodes)
    .HasForeignKey(zc => zc.NeighborhoodId)
    .WillCascadeOnDelete(false);

Delete cascade on HbZipcode now occurs only when HbCity is deleted

What's happening here is that HbZipCode has foreign keys to multiple tables, and you can't create 2+ foreign key constraint with ON CASCADE DELETE that have multiple ways of deleting the same rows from the same table.

It's likely that your entity classes are set up such that when HbZipCode is deleted, it cascades the delete to HbNeighborhood, then HbCity, then HbState, and then HbCountry. If you added another foreign key to HbZipCode with ON CASCADE DELETE pointing to HbCity, deleting an HbZipCode record would result in a direct cascade delete to HbNeighborhood and a direct cascade delete to HbCity, but the HbNeighborhood being deleted would also cause a cascade delete to HbCity.

What you need to do is resolve the multiple cascade delete paths to HbCity and the other entity types by turning off CASCADE DELETE for most of them.

See this MSDN page on fluent configuration.

It's likely that you want something like this:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<HbZipCode>() 
        .HasRequired(t => t.HbCity)
        .WithMany(t => t.HbZipCodes)
        .HasForeignKey(t => t.CityId)
        .WillCascadeOnDelete(false);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM