asp.net - Entity Framework: comment résoudre "FOREIGN KEY contrainte peut provoquer des cycles ou plusieurs chemins en cascade"?




entity-framework sqlmembershipprovider (4)

il y a beaucoup de questions sur ce problème, mais je n'ai pas pu résoudre mon cas. quelqu'un peut-il s'il vous plaît jeter un oeil à ceci:

J'ai une table de Office qui a une relation un-plusieurs avec des tables de Doctor et de Secretary . Les deux dernières tables sont dérivées de la table Employee qui a une relation de clé primaire partagée avec la table Users prédéfinie créée par sqlmembershipprovider . Il semble qu'il y ait une relation many-many entre la table Users et la table Roles , que je n'ai pas dans la main.

Mon problème était de créer une relation (zéro, un) - (un) entre ma table des Employee et cette table des Users que j'ai terminée avec une relation de clé primaire partagée entre eux et l'erreur soulevée, alors. (Y a-t-il une meilleure solution pour ce problème?)

voici l'erreur:

L'introduction de la contrainte FOREIGN KEY 'FK_dbo.aspnet_UsersInRoles_dbo.aspnet_Users_UserId' sur la table 'aspnet_UsersInRoles' peut provoquer des cycles ou plusieurs chemins en 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.

Voici mes codes et codes d'adhésion après ingénierie inverse:

public class Office
{
    public Office()
    {
        this.Doctors = new HashSet<Doctor>();
        this.Secretaries = new HashSet<Secretary>();
    }

    [Key]
    public System.Guid OfficeId { get; set; }
    public virtual ICollection<Doctor> Doctors { get; set; }
    public virtual ICollection<Secretary> Secretaries { get; set; }
}

public class Employee
{
    [Key, ForeignKey("User")]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public System.Guid Id { get; set; }
    public string Name { get; set; }

    [ForeignKey("Office")]
    public System.Guid OfficeId { get; set; }

    // shared primary key 
    public virtual aspnet_Users User { get; set; }

    public virtual Office Office { get; set; }
}

public class Doctor :Employee
{
    public Doctor()
    {
        this.Expertises = new HashSet<Expertise>();
    }
    //the rest..    
    public virtual ICollection<Expertise> Expertises { get; set; }
}

public class Secretary : Employee
{
    // blah blah
}

public class aspnet_Users
{
    public aspnet_Users()
    {
        this.aspnet_Roles = new List<aspnet_Roles>();
    }

    public System.Guid ApplicationId { get; set; }
    public System.Guid UserId { get; set; }
    //the rest..
    public virtual aspnet_Applications aspnet_Applications { get; set; }
    public virtual ICollection<aspnet_Roles> aspnet_Roles { get; set; }
}

public class aspnet_Roles
{
    public aspnet_Roles()
    {
        this.aspnet_Users = new List<aspnet_Users>();
    }

    public System.Guid ApplicationId { get; set; }
    public System.Guid RoleId { get; set; }
    //the rest..
    public virtual aspnet_Applications aspnet_Applications { get; set; }
    public virtual ICollection<aspnet_Users> aspnet_Users { get; set; }
}

EDIT: et les relations vont plus loin, il existe une relation multiple entre la table Users et la table Applications , également entre les Roles et les Applications .


En fonction de vos commentaires, le problème est que vous utilisez le même PK dans les deux tableaux. Je changerais cela tout de suite, les utilisateurs PK comme un champ supplémentaire dans les employés avec une relation FK aux utilisateurs (un à un je suppose). Et ajouter un PK indépendant aux utilisateurs (Un autre guid pour respecter le reste de vos tables). Si vous voulez garantir que la nouvelle clé étrangère dans Employés (celle qui pointe vers Utilisateurs) est unique, vous pouvez toujours ajouter un index unique.

De cette façon, vous gardez votre structure tout de même et vous vous débarrassez du cycle.


Juste une mise à jour :

Comme d'autres réponses suggèrent que vous ne devez pas faire d'action sur la suppression. La manière mise à jour de le faire est la suivante pour Entityframework Core 1.0

table.ForeignKey(name: "FK_Cities_Regions_RegionId",
                 column: x => x.RegionId,
                 principalTable: "Regions",
                 principalColumn: "RegionId",
                 onDelete: ReferentialAction.NoAction);

REMARQUE: Ne ReferentialAction.NoAction on on onDelete


Vous pouvez utiliser l'API classique pour spécifier les actions suggérées par le message d'erreur.

Dans votre contexte:

protected override void OnModelCreating( DbModelBuilder modelBuilder )
{
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<aspnet_UsersInRoles>().HasMany(i => i.Users).WithRequired().WillCascadeOnDelete(false);
}

Notez que vous n'avez pas inclus la définition de la table aspnet_UsersInRoles donc ce code peut ne pas fonctionner.

Une autre option consiste à supprimer tous les CASCADE DELETES en ajoutant

modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

Si vous avez besoin de plus d'informations sur la configuration des relations avec l'API fluide, je suggère http://msdn.microsoft.com/en-US/data/jj591620


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

Ajouter ce code en contexte







sqlmembershipprovider