visual tutorial studio net mvc framework first español asp asp.net entity-framework sqlmembershipprovider

asp.net - tutorial - membership asp net visual studio 2015



Entity Framework: cómo resolver "FOREIGN KEY constraint puede causar ciclos o múltiples caminos en cascada"? (5)

hay muchas preguntas sobre este problema, pero no pude resolver mi caso. ¿alguien puede echar un vistazo a esto?

Tengo una mesa de Office que tiene una relación uno-muchos con las tablas Doctor y Secretary . Las dos últimas tablas se derivan de la tabla Employee , que tiene una relación shared-primary-key con una tabla predefinida de Users creada por sqlmembershipprovider . Parece que hay una relación de muchos y muchos entre la tabla de Users y la tabla de Roles , que no tengo nada que ver.

Mi problema fue crear una relación (cero, uno) - (uno) entre mi tabla de Employee y esa tabla de Users que terminé con una relación de clave primaria compartida entre ellos y el error planteado, entonces. (¿Hay una mejor solución para ese problema?)

aquí está el error:

La introducción de la restricción FOREIGN KEY ''FK_dbo.aspnet_UsersInRoles_dbo.aspnet_Users_UserId'' en la tabla ''aspnet_UsersInRoles'' puede provocar ciclos o múltiples rutas en cascada. Especifique ON DELETE NO ACTION o ON UPDATE NO ACTION, o modifique otras restricciones FOREIGN KEY. No se pudo crear una restricción. Ver errores previos.

aquí están mis códigos y códigos de membresía después de ingeniería inversa:

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; } }

EDITAR: y las relaciones son más profundas, hay una relación de muchos y uno entre la tabla Users y la tabla de Applications , también entre Roles y Applications .


Puede usar la API fluida para especificar las acciones que sugiere el mensaje de error.

En tu contexto:

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

Tenga en cuenta que no ha incluido la definición de la tabla aspnet_UsersInRoles, por lo que este código puede no funcionar.

Otra opción es eliminar todos los DELETES DE CASCADE agregando esto

modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

Si necesita más información sobre la configuración de las relaciones con la API fluida, sugiero http://msdn.microsoft.com/en-US/data/jj591620


Según sus comentarios, el problema es que está usando el mismo PK en ambas tablas. Me gustaría cambiar eso de inmediato, tener Users PK como un campo adicional en Employees con una relación FK con los usuarios (supongo de uno a uno). Y agregue un PK independiente a los usuarios (Otro guid para respetar el resto de sus tablas). Si desea garantizar que la nueva clave externa en Empleados (la que apunta a los Usuarios) es única, siempre puede agregar un Índice único.

De esa manera, mantienes tu estructura de la misma manera y te deshaces del ciclo.


Solo una actualización :

Como otras respuestas sugieren que NO debes realizar ninguna acción sobre la eliminación. La forma actualizada de hacerlo es la siguiente para Entityframework Core 1.0

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

NOTA: Hacer ReferentialAction.NoAction en onDelete


También puedes modificar tu clase de migración. En mi caso, en la clase de migración fue:

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);

Después de eliminar "cascadeDelete: true", la base de datos de actualización funciona perfectamente.

O como false

.ForeignKey("dbo.Categories", t => t.CategoryId, cascadeDelete: false)


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

Agregar este código en contexto