I have 6 entities in total but my issue is with these following 3:
Departement
, Filier
and Etudiant
.
The Departement
entity contains many Filiere
and many Etudiant
entities, while Filiere
and Etudiant
are only associate with 1 Departement
each.
This is my error message after adding migration and trying to update the database for the first time:
Introducing FOREIGN KEY constraint 'FK_Etudiant_Filiere_FiliereId' on table 'Etudiant' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Could not create constraint or index. See previous errors.
This is my Departement
entity:
using System.ComponentModel.DataAnnotations;
namespace Scolarité.Models
{
public class Departement
{
public int Id { get; set; }
[Required(ErrorMessage = "Libellé Obligatoire")]
[StringLength(100, MinimumLength = 3)]
[Display(Name = "Departement")]
public string LibelleD { get; set; }
[Required(ErrorMessage = "Chef Departement Obligatoire")]
[StringLength(30, MinimumLength = 3)]
[Display(Name = " Chef Departement")]
public string ChefD { get; set; }
public virtual ICollection<Filiere> Filieres { get; set; }
public virtual ICollection<Semestre> Semestre { get; set; }
public virtual ICollection<Unite> Unite { get; set; }
public virtual ICollection<Etudiant> Etudiant { get; set; }
}
}
This is my Filiere
entity:
using System.ComponentModel.DataAnnotations;
namespace Scolarité.Models
{
public class Filiere
{
public int Id { get; set; }
[Required(ErrorMessage = "Libellé filiére Obligatoire")]
[StringLength(100, MinimumLength = 3)]
[Display(Name = " Libelle Filiére")]
public string LibelleF { get; set; }
public int DepartementId { get; set; }
public virtual Departement Departement { get; set; }
public virtual ICollection<Etudiant> Etudiants { get; set; }
public virtual ICollection<Unite> Unite { get; set; }
public virtual ICollection<Semestre> Semestre { get; set; }
}
}
This is my Etudiant
entity:
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Scolarité.Models
{
public class Etudiant
{
public int Id { get; set; }
[Required(ErrorMessage = "Nom Obligatoire")]
[StringLength(30, MinimumLength = 3)]
public string Nom { get; set; }
[Required(ErrorMessage = "Prenom Obligatoire")]
[StringLength(30, MinimumLength = 3)]
public string Prenom { get; set; }
[Required(ErrorMessage = "CIN Obligatoire")]
[RegularExpression(@"^\d{8}$", ErrorMessage = "Le CIN doit comporter 8 chiffres.")]
public string Cin { get; set; }
[Required(ErrorMessage = "Mot de passe Obligatoire")]
[DataType(DataType.Password)]
public string Password { get; set; }
[Display(Name = " Departement")]
public int DepartementId { get; set; }
public virtual Departement Departement { get; set; }
[Display(Name = " Filiére")]
public int FiliereId { get; set; }
public virtual Filiere Filiere { get; set; }
}
}
I checked youtube videos and other posts relating to my problem on stackoverflow and tried their solutions but they didn't work for me, although I believe I'm most likely implementing them incorrectly, and that's why I'm here now.
I tried making the foreign keys nullable even though they shouldn't be for my case, but that didn't solve the problem
I tried changing the onDelete
option to NoAction
and to ClientSetNull
by going to my DbContext
and adding the following code to the OnModelCreating(ModelBuilder modelBuilder)
method, but it still throws the same error message as if though I didn't change a thing:
OnModelCreating
method for my DbContext
:
using Microsoft.EntityFrameworkCore;
using Scolarité.Models;
public class ScolaritéContext : DbContext
{
public ScolaritéContext(DbContextOptions<ScolaritéContext> options)
: base(options)
{
}
public DbSet<Departement> Departement { get; set; } = default!;
public DbSet<EE> EE { get; set; } = default!;
public DbSet<Etudiant> Etudiant { get; set; } = default!;
public DbSet<Filiere> Filiere { get; set; } = default!;
public DbSet<Semestre> Semestre { get; set; } = default!;
public DbSet<Unite> Unite { get; set; } = default!;
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Departement>()
.HasMany(d => d.Filieres)
.WithOne(f => f.Departement)
.HasForeignKey(f => f.DepartementId)
.OnDelete(DeleteBehavior.NoAction);
modelBuilder.Entity<Filiere>()
.HasMany(f => f.Etudiants)
.WithOne(e => e.Filiere)
.HasForeignKey(e => e.FiliereId)
.OnDelete(DeleteBehavior.NoAction);
modelBuilder.Entity<Etudiant>()
.HasOne(e => e.Departement)
.WithMany(d => d.Etudiant)
.HasForeignKey(e => e.DepartementId)
.OnDelete(DeleteBehavior.NoAction);
modelBuilder.Entity<Etudiant>()
.HasOne(e => e.Filiere)
.WithMany(f => f.Etudiants)
.HasForeignKey(e => e.FiliereId)
.OnDelete(DeleteBehavior.NoAction);
}
}
Without using .OnDelete(DeleteBehavior.NoAction);
, adding following code to modelbuilder solved my problem:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
...
if (modelBuilder == null)
throw new ArgumentNullException("modelBuilder");
// for the other conventions, we do a metadata model loop
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{
// equivalent of modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
entityType.SetTableName(entityType.DisplayName());
// equivalent of modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
entityType.GetForeignKeys()
.Where(fk => !fk.IsOwnership && fk.DeleteBehavior == DeleteBehavior.Cascade)
.ToList()
.ForEach(fk => fk.DeleteBehavior = DeleteBehavior.Restrict);
}
base.OnModelCreating(modelBuilder);
...
}