il y a beaucoup de questions sur ce problème, mais je n'ai pas pu résoudre mon cas. quelqu'un peut-il jeter un oeil à ceci:
J'ai une table Office
qui a une relation un-plusieurs avec les tables Doctor
et 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 existe une relation plusieurs-plusieurs entre la table Users
et la table Roles
que je n'ai pas en main.
Mon problème était de créer une relation (zéro, un) n) entre ma table Employee
et cette table Users
que j'ai terminée avec une relation de clé primaire partagée entre eux et l'erreur soulevée, puis. (Existe-t-il une meilleure solution à 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 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.
voici mes codes et codes d'adhésion après reverse engineering:
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 Users
table et Applications
table, également entre Roles
et Applications
aussi.
Vous pouvez utiliser l'API couramment 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 ceci
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/jj59162
Vous pouvez également modifier votre classe de migration. Dans mon cas, dans la classe de migration était:
CreateTable(
"dbo.Spendings",
c => new
{
SpendingId = c.Int(nullable: false, identity: true),
CategoryGroupId = c.Int(nullable: false),
CategoryId = c.Int(nullable: false),
Sum = c.Single(nullable: false),
Date = c.DateTime(nullable: false),
Comment = c.String(),
UserId = c.String(),
LastUpdate = c.String(),
})
.PrimaryKey(t => t.SpendingId)
.ForeignKey("dbo.Categories", t => t.CategoryId, cascadeDelete: true)
.ForeignKey("dbo.CategoryGroups", t => t.CategoryGroupId, cascadeDelete: true)
.Index(t => t.CategoryGroupId)
.Index(t => t.CategoryId);
Après avoir supprimé "cascadeDelete: true", Update-Database fonctionne parfaitement.
OU comme false
.ForeignKey("dbo.Categories", t => t.CategoryId, cascadeDelete: false)
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
}
Ajoutez ce code en contexte
Sur la base de vos commentaires, le problème est que vous utilisez le même PK dans les deux tableaux. Je changerais cela tout de suite, j'aurais les utilisateurs PK comme champ supplémentaire dans les employés ayant une relation FK avec les utilisateurs (un à un, je suppose). Et ajoutez un PK indépendant aux utilisateurs (Un autre guide pour respecter le reste de vos tables). Si vous souhaitez garantir que la nouvelle clé étrangère dans Employees (celle qui pointe vers les 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 un mise à jour:
Comme d'autres réponses le suggèrent, vous ne devez PAS effectuer d'action sur la suppression. La méthode mise à jour 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: faites ReferentialAction.NoAction
sur onDelete