web-dev-qa-db-fra.com

L'introduction de la contrainte FOREIGN KEY peut provoquer des cycles ou plusieurs chemins en cascade

Je reçois cette erreur

L'introduction de la contrainte FOREIGN KEY 'FK_dbo.Regions_dbo.Countries_CountryId' sur la table 'Regions' peut provoquer des cycles ou plusieurs chemins de cascade. Spécifiez ON DELETE NO ACTION ou ON UPDATE NO ACTION, ou modifiez d'autres contraintes FOREIGN KEY. Impossible de créer une contrainte. Voir les erreurs précédentes.

Je me demande si cela signifie que la conception de ma base de données est mauvaise? J'ai lu que vous éteignez les cascades ou quelque chose comme ça, mais je ne sais tout simplement pas si cela fait disparaître le problème du tapis.

Je laisse simplement EF générer mes tables via ma classe de domaine (je n'utilise aucune annotation de données ou mappage fluide à ce stade).

       public class Country
        {
            public Country()
            {
                this.Stores = new List<Store>();
                this.Regions = new List<Region>();
                Id = GuidCombGenerator.GenerateComb();
            }

            public Guid Id { get; private set; }

            private string name;

            public string Name
            {
                get { return name; }
                set
                {
                    name = value.Trim();
                }
            }

            private string code;

            public string Code
            {
                get { return code; }
                set
                {
                    code = value.Trim();
                }
            }

            public virtual ICollection<Store> Stores { get; set; }
            public virtual ICollection<Region> Regions { get; set; }
        }


          public class City
        {
            public City()
            {
                this.Stores = new List<Store>();
                Id = GuidCombGenerator.GenerateComb();
            }

            public Guid Id { get; private set; }

            private string name;

            public string Name
            {
                get { return name; }
                set
                {
                    name = value.Trim();
                }
            }


            public Guid RegionId { get; set; }
            public virtual Region Region { get; set; }

            public virtual ICollection<Store> Stores { get; set; }
        }


            public class Region
        {
            public Region()
            {
                this.Cities = new List<City>();
              this.Stores = new List<Store>();


                Id = GuidCombGenerator.GenerateComb();
            }

            public Guid Id { get; private set; }


            private string state;

            public string State
            {
                get { return state; }
                set
                {
                    state = value.Trim();
                }
            }


            public Guid CountryId { get; set; }
            public virtual ICollection<City> Cities { get; set; }
            public virtual Country Country { get; set; }
           public virtual ICollection<Store> Stores { get; set; }
        }


  public class Store
    {
        public Store()
        {
            Id = GuidCombGenerator.GenerateComb();

            Users = new List<User>();
        }

        public Guid Id { get; private set; }

        public Guid CountryId { get; set; }
        public Guid CityId { get; set; }
        public Guid RegionId { get; set; }
        public virtual City City { get; set; }
        public virtual Country Country { get; set; }
        public virtual Region Region { get; set; }

        public virtual ICollection<User> Users { get; set; }

    }

Serait-ce à cause des magasins?

31
chobo2

Toutes les relations dans votre modèle sont obligatoire car toutes les propriétés de clé étrangère (CountryId, RegionId, CityId) sont non nullable =. Pour les relations un à plusieurs requises, EF activera la suppression en cascade par convention.

Country et Region ont plusieurs chemins de suppression vers la table Store, par exemple si vous supprimez un Country les Stores associés peuvent être supprimés via trois chemins en cascade différents (ce qui n'est pas autorisé avec SQL Server):

  • Country -> Store
  • Country -> Region -> Store
  • Country -> Region -> City -> Store

Vous devez éviter ces chemins de suppression ambigus en désactivant la suppression en cascade à l'aide de l'API Fluent ou en définissant certaines des relations comme facultatif (avec une clé étrangère nullable Guid?).

Ou supprimez les collections Stores (et les références inverses et les propriétés FK) de toutes les entités à l'exception de City. Pour moi, ces collections semblent redondantes car vous pouvez trouver tous les magasins dans un Country en parcourant le Regions.Cities.Stores collections.

54
Slauma

Ajoutez modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>() dans la méthode OnModelCreating de votre fichier DataContext comme suit:

public class YourDataContext : DbContext
{
    public DbSet<Country> Countries{ get; set; }
    ...


    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

    }
}

La même question: entité-framework-comment-résoudre-la-clé-étrangère-contrainte-peut-provoquer-cycles-ou-multi

24
Morteza