Laden...

Entity Framework Code First: FOREIGN KEY constraint may cause cycles or multiple cascade paths

Erstellt von Steffo vor 10 Jahren Letzter Beitrag vor 10 Jahren 5.042 Views
S
Steffo Themenstarter:in
45 Beiträge seit 2013
vor 10 Jahren
Entity Framework Code First: FOREIGN KEY constraint may cause cycles or multiple cascade paths

Hallo,
ich versuche mich gerade an Code First und stoße immer wieder auf Probleme...
Eine Person soll mehrere Meetings haben können und ein Meeting besteht aus genau zwei Personen:

    public abstract class Person
    {
        public int PersonID { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }

        public virtual ICollection<Meeting> Meeting { get; set; }
    }
    public class Meeting
    {
        public int MeetingID { get; set; }

        [ForeignKey("Customer")]
        public int CustomerID { get; set; }

        [ForeignKey("SalesAgent")]
        public int SalesAgentID { get; set; }

        public virtual Person Customer { get; set; }
        public virtual Person SalesAgent { get; set; }
    }

Folgenden Fehler bekomme ich, wenn ich update-database in der Paket Manager-Konsole durchführe:

Fehlermeldung:
Introducing FOREIGN KEY constraint 'FK_dbo.Meeting_dbo.Person_SalesAgentID' on table 'Meeting' 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. See previous errors.

Wenn ich nun nachträglich im Migrationsskript cascadeDelete auf false setze, ist alles gut:

            AddForeignKey("dbo.Meeting", "CustomerID", "dbo.Person", "PersonID", cascadeDelete: false);
            AddForeignKey("dbo.Meeting", "SalesAgentID", "dbo.Person", "PersonID", cascadeDelete: false);

Wenn ich diese aber wieder auf true setze und versuche das über den modelBuilder zu beheben...

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Meeting>().HasRequired(m => m.SalesAgent).WithMany(p => p.Meeting).WillCascadeOnDelete(false);
            modelBuilder.Entity<Meeting>().HasRequired(m => m.Customer).WithMany(p => p.Meeting).WillCascadeOnDelete(false);
        }

... dann bekomme ich folgende Fehlermeldung:> Fehlermeldung:

System.NullReferenceException: Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt.
bei System.Data.Entity.ModelConfiguration.Configuration.Types.EntityTypeConfiguration.Configure(EdmEntityType entityType, EdmModel model)
bei System.Data.Entity.ModelConfiguration.Configuration.ModelConfiguration.ConfigureEntities(EdmModel model)
bei System.Data.Entity.DbModelBuilder.Build(DbProviderManifest providerManifest, DbProviderInfo providerInfo)
bei System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection)
bei System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext)
bei System.Data.Entity.Internal.RetryLazy2.GetValue(TInput input) bei System.Data.Entity.Internal.LazyInternalContext.InitializeContext() bei System.Data.Entity.Internal.LazyInternalContext.get_CodeFirstModel() bei System.Data.Entity.Infrastructure.EdmxWriter.WriteEdmx(DbContext context, XmlWriter writer) bei System.Data.Entity.Migrations.Extensions.DbContextExtensions.&lt;&gt;c__DisplayClass1.&lt;GetModel&gt;b__0(XmlWriter w) bei System.Data.Entity.Migrations.Extensions.DbContextExtensions.GetModel(Action1 writeXml)
bei System.Data.Entity.Migrations.Extensions.DbContextExtensions.GetModel(DbContext context)
bei System.Data.Entity.Migrations.DbMigrator..ctor(DbMigrationsConfiguration configuration, DbContext usersContext)
bei System.Data.Entity.Migrations.DbMigrator..ctor(DbMigrationsConfiguration configuration)
bei System.Data.Entity.Migrations.Design.ToolingFacade.BaseRunner.GetMigrator()
bei System.Data.Entity.Migrations.Design.ToolingFacade.UpdateRunner.RunCore()
bei System.Data.Entity.Migrations.Design.ToolingFacade.BaseRunner.Run()

Weiß jemand weiter?! Code First ist an sich eine geniale Idee, aber es kann nicht sein, dass etwas, dass in SQL total leicht umzusetzen ist, mit Code First solche doofen Probleme macht!!!

L. G.
Steffo

M
402 Beiträge seit 2005
vor 10 Jahren

Hallo Steffo,

den Fehler den du bei "Update-Database" bekommst liefert nicht das Entity Framework sondern die Datenbank (SQL-Server nehm ich an).

Und der Grund dafür steht eigentlich in diesem Fehler.
Dem Entity Framework die Schuld dafür zu geben ist daher nicht angebracht.

etwas, dass in SQL total leicht umzusetzen ist

Das ist auch mit SQL nicht total leicht umzusetzen.
=> "may cause cycles or multiple cascade paths"

S
Steffo Themenstarter:in
45 Beiträge seit 2013
vor 10 Jahren

Hallo M@TUK,
deswegen wollte ich ja Cascade Delete über die Fluent-API auf false setzen, aber das gelingt mir nur, wenn ich das direkt im Migrationsskript mache. Das Migrationsskript möchte ich aber jederzeit verwerfen und über Code First und der Fluent-API neu erstellen können.

Weißt du da vielleicht weiter?!

L. G.
Steffo

V
162 Beiträge seit 2010
vor 10 Jahren

Hi,

versuchs mal hiermit.


    public class Person
    {
        public Person()
        {
            Meeting = new Collection<Meeting>();
        }
        [Key]
        public int PersonID { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }

        public virtual ICollection<Meeting> Meeting { get; set; }
    }

    public class Meeting
    {
        [Key]
        public int MeetingID { get; set; }

        public int CustomerID { get; set; }
        [ForeignKey("CustomerID")]
        public virtual Person Customer { get; set; }

        public int SalesAgentID { get; set; }
        [ForeignKey("SalesAgentID")]
        public virtual Person SalesAgent { get; set; }
    }

MfG
Björn

Das Leben ist schön!

16.827 Beiträge seit 2008
vor 10 Jahren

Wenn man mit der FluentAPI arbeitet, sollte man i.d.R. die Attribut-Definitionen weglassen und eben alles via Fluent deklarieren.

S
Steffo Themenstarter:in
45 Beiträge seit 2013
vor 10 Jahren

Ich habs nun anders gelöst: Many to Many, d. h., sowohl Person als auch Meeting haben eine Collection des jeweils anderen Entitättyps. Eigentlich wollte ich genau zwei Instanzen von Person in Meeting haben, aber das schien Code First irgendwie zu verwirren...

Dennoch danke, für eure Antworten! 😃

L. G.
Steffo

16.827 Beiträge seit 2008
vor 10 Jahren

Nö. Das geht eigentlich ziemlich gut, wenn mans richtig definiert.