He estado luchando con esto por un tiempo y no puedo entender qué está sucediendo. Tengo una entidad de tarjeta que contiene lados (generalmente 2), y tanto las cartas como los lados tienen un escenario. Estoy usando migraciones EF Codefirst y las migraciones fallan con este error:
La introducción de la restricción FOREIGN KEY 'FK_dbo.Sides_dbo.Cards_CardId' en la tabla 'Sides' puede causar ciclos o múltiples rutas en cascada. Especifique ON DELETE NO ACTION o ON UPDATE NO ACTION, o modifique otras restricciones de FOREIGN KEY.
Aquí está mi entidad de tarjeta :
public class Card
{
public Card()
{
Sides = new Collection<Side>();
Stage = Stage.ONE;
}
[Key]
[Required]
public virtual int CardId { get; set; }
[Required]
public virtual Stage Stage { get; set; }
[Required]
[ForeignKey("CardId")]
public virtual ICollection<Side> Sides { get; set; }
}
Aquí está mi entidad secundaria :
public class Side
{
public Side()
{
Stage = Stage.ONE;
}
[Key]
[Required]
public virtual int SideId { get; set; }
[Required]
public virtual Stage Stage { get; set; }
[Required]
public int CardId { get; set; }
[ForeignKey("CardId")]
public virtual Card Card { get; set; }
}
Y aquí está mi entidad Stage :
public class Stage
{
// Zero
public static readonly Stage ONE = new Stage(new TimeSpan(0, 0, 0), "ONE");
// Ten seconds
public static readonly Stage TWO = new Stage(new TimeSpan(0, 0, 10), "TWO");
public static IEnumerable<Stage> Values
{
get
{
yield return ONE;
yield return TWO;
}
}
public int StageId { get; set; }
private readonly TimeSpan span;
public string Title { get; set; }
Stage(TimeSpan span, string title)
{
this.span = span;
this.Title = title;
}
public TimeSpan Span { get { return span; } }
}
Lo extraño es que si agrego lo siguiente a mi clase Stage:
public int? SideId { get; set; }
[ForeignKey("SideId")]
public virtual Side Side { get; set; }
La migración se ejecuta con éxito. Si abro SSMS y miro las tablas, puedo ver que Stage_StageId
se ha agregado a Cards
(como se esperaba / desea), sin embargo, no Sides
contiene ninguna referencia a Stage
(no se espera).
Si luego agrego
[Required]
[ForeignKey("StageId")]
public virtual Stage Stage { get; set; }
public int StageId { get; set; }
Para mi clase Side, veo una StageId
columna agregada a mi Side
tabla.
Esto está funcionando, pero ahora en toda mi aplicación, cualquier referencia a Stage
contiene un SideId
, que en algunos casos es totalmente irrelevante. Me gustaría darles a mis Card
y Side
entidades una Stage
propiedad basada en la clase Stage anterior sin contaminar la clase stage con propiedades de referencia si es posible ... ¿qué estoy haciendo mal?
Side
clase agregue un entero anulable y elimine el[Required]
atributo =>public int? CardId { get; set; }
DeleteBehavior.Restrict
oDeleteBehavior.SetNull
.Respuestas:
Debido a que
Stage
es obligatorio , todas las relaciones de uno a muchos que esténStage
involucradas tendrán la eliminación en cascada habilitada de forma predeterminada. Significa que si elimina unaStage
entidadSide
Card
y debidoCard
ySide
tener una requerido uno-a-muchos relación con la eliminación en cascada activada por defecto de nuevo, a continuación, caerá en cascada a partirCard
deSide
Por lo tanto, tiene dos rutas de eliminación en cascada de
Stage
aSide
, lo que provoca la excepción.Debe hacer lo
Stage
opcional en al menos una de las entidades (es decir, eliminar el[Required]
atributo de lasStage
propiedades) o deshabilitar la eliminación en cascada con Fluent API (no es posible con anotaciones de datos):fuente
Stage
. Otras relaciones permanecen sin cambios.Stage
eliminación en cascada,Side
tanto directamente como a través de unCard
Tenía una tabla que tenía una relación circular con los demás y recibía el mismo error. Resulta que se trata de la clave externa que no era anulable. Si la clave no es anulable, el objeto relacionado debe eliminarse y las relaciones circulares no lo permiten. Por lo tanto, use una clave foránea anulable.
fuente
int?
lugar deint
dejarla anulable.Cualquiera que se pregunte cómo hacerlo en EF core:
fuente
builder.HasOne(x => x.Stage).WithMany().HasForeignKey(x => x.StageId).OnDelete(DeleteBehavior.Restrict);
builder _ .Entity<TEntity>() _
anterior,HasOne()
se puede llamar ...IEntityTypeConfiguration<T>
. No recuerdo haber visto elbuilder.Entity<T>
método esos días, pero podría estar equivocado. Sin embargo, ambos funcionarán :)Recibí este error para muchas entidades cuando estaba migrando de un modelo EF7 a una versión EF6. No quería tener que pasar por cada entidad de a una por vez, así que solía:
fuente
Puede establecer cascadeDelete en falso o verdadero (en su método de migración Up ()). Depende de su requerimiento.
fuente
UP
método podría ser modificado por operaciones externas.En .NET Core cambié la opción onDelete a ReferencialAction.NoAction
fuente
También tuve este problema, lo resolví al instante con esta respuesta de un hilo similar
En mi caso, no quería eliminar el registro dependiente en la eliminación de clave. Si este es el caso en su situación, simplemente cambie el valor booleano en la migración a falso:
Lo más probable es que si está creando relaciones que arrojan este error de compilación pero SI desean mantener la eliminación en cascada; Tienes un problema con tus relaciones.
fuente
Arreglé esto. Cuando agrega la migración, en el método Up () habrá una línea como esta:
Si solo borras el cascadeDelete desde el final, funcionará.
fuente
Solo para fines de documentación, para alguien que viene en el futuro, esto se puede resolver de una manera tan simple como esto, y con este método, podría hacer un método que se deshabilitó una vez, y podría acceder a su método normalmente
Agregue este método a la clase de base de datos de contexto:
fuente
Esto suena extraño y no sé por qué, pero en mi caso eso estaba sucediendo porque mi ConnectionString estaba usando "." en el atributo "fuente de datos". Una vez que lo cambié a "localhost" funcionó a las mil maravillas. No se necesitaba otro cambio.
fuente
En .NET Core jugué con todas las respuestas superiores, pero sin ningún éxito. Hice muchos cambios en la estructura de la base de datos y cada vez agregué nuevas migraciones intentando
update-database
, pero recibí el mismo error.Luego comencé
remove-migration
uno por uno hasta que Package Manager Console me arrojó una excepción:Después de eso, agregué nueva migración (
add-migration
) y conupdate-database
éxitoEntonces, mi sugerencia sería: eliminar todas las migraciones temporales, hasta el estado actual de la base de datos.
fuente
Las respuestas existentes son geniales, solo quería agregar que me encontré con este error por una razón diferente. Quería crear una migración EF inicial en una base de datos existente pero no utilicé -IgnoreChanges indicador y apliqué el comando Actualizar-Base de datos en una Base de datos vacía (también en las existentes).
En cambio, tuve que ejecutar este comando cuando la estructura de db actual es la actual:
Es probable que haya un problema real en la estructura de base de datos, pero salve al mundo paso a paso ...
fuente
La forma más sencilla es editar el archivo de migración
(cascadeDelete: true)
en el archivo(cascadeDelete: false)
después de asignar el comando Actualizar base de datos en la Consola del Administrador de paquetes. Si hay algún problema con su última migración, está bien. De lo contrario, verifique su historial de migración anterior, copie esas cosas, péguelo en su último archivo de migración, luego haga lo mismo. A mí me funciona perfectamente.fuente
Cuando su migración falla, se le dan un par de opciones: 'Introducción de la restricción FOREIGN KEY' FK_dbo.RecommendedBook_dbo.Department_DepartmentID 'en la tabla' RecommendedBook 'puede causar ciclos o múltiples rutas en cascada. Especifique ON DELETE NO ACTION o ON UPDATE NO ACTION, o modifique otras restricciones de FOREIGN KEY. No se pudo crear restricción o índice. Ver errores anteriores.
Aquí hay un ejemplo del uso de 'modificar otras restricciones de CLAVE EXTRANJERA' estableciendo 'cascadeDelete' en falso en el archivo de migración y luego ejecute 'update-database'.
fuente
Ninguna de las soluciones mencionadas funcionó para mí. Lo que tenía que hacer era usar un int anulable (int?) En la clave externa que no era necesaria (o no una clave de columna no nula) y luego eliminar algunas de mis migraciones.
Comience eliminando las migraciones, luego intente con int.
El problema fue tanto la modificación como el diseño del modelo. No fue necesario cambiar el código.
fuente
Haga que sus atributos de clave externa sean anulables. Que funcionará.
fuente