[.net] قد يتسبب إدخال قيد مفتاح FOREIGN في حدوث دورات أو مسارات متسلسلة متعددة - لماذا؟


Answers

كان لدي جدول ذو علاقة دائرية مع الآخرين وكنت أتلقى نفس الخطأ. تبين أنه يدور حول المفتاح الخارجي الذي لم يكن ملغيا. إذا كان المفتاح لا يجب حذف كائن ذو صلة nullable والعلاقات الدائرية لا تسمح بذلك. لذلك استخدم المفتاح الخارجي nullable.

[ForeignKey("StageId")]
public virtual Stage Stage { get; set; }
public int? StageId { get; set; }
Question

لقد كنت أتصارع مع هذا لفترة من الوقت ولا أستطيع معرفة ما يحدث. لدي كيان البطاقة الذي يحتوي على الأوجه (عادة 2) - وكل من البطاقات والوجهات يكون لها مرحلة. إنني أستخدم عمليات ترحيل EF Codefirst ولا تنجح عمليات الترحيل في هذا الخطأ:

إدخال قيد مفتاح FOREIGN 'FK_dbo.Sides_dbo.Cards_CardId' في الجدول 'Sides' قد يتسبب في دورات أو مسارات متتالية متعددة. حدد ON DELETE NO ACTION أو ON UPDATE NO ACTION ، أو قم بتعديل القيود الأخرى FOREIGN KEY.

إليك كيان بطاقتي :

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

هنا كياني الجانبي :

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

}

وإليكم كيان المرحلة :

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

الشيء الغريب هو أنني إذا أضفت التالي إلى صف المرحلة الخاصة بي:

    public int? SideId { get; set; }
    [ForeignKey("SideId")]
    public virtual Side Side { get; set; }

يتم تشغيل الترحيل بنجاح. إذا فتحت SSMS Stage_StageId الجداول ، يمكنني أن أرى أن Stage_StageId قد تمت إضافته إلى Cards (كما هو متوقع / مرغوب) ، لكن Sides لا يحتوي على أي إشارة إلى Stage (غير متوقع).

إذا قمت بعد ذلك بإضافة

    [Required]
    [ForeignKey("StageId")]
    public virtual Stage Stage { get; set; }
    public int StageId { get; set; }

إلى صف جانبي ، أرى عمود StageId مضافًا إلى الجدول Side بي.

هذا هو العمل ، ولكن الآن في جميع أنحاء طلبي ، أي إشارة إلى Stage تحتوي على SideId ، وهو في بعض الحالات غير ذي صلة تماما. أود فقط أن أمنح كنيستي Card والجهات Side خاصية Stage استنادًا إلى فئة المرحلة المذكورة أعلاه دون تلويث فئة المسرح مع خصائص المرجعية إن أمكن ... ماذا أفعل الخطأ؟




كان لي هذه المسألة أيضا ، أنا حلها على الفور مع هذه الإجابة من موضوع مماثل

في حالتي ، لم أكن أرغب في حذف السجل التابع عند حذف المفتاح. إذا كانت هذه هي الحالة في موقفك ، فما عليك سوى تغيير القيمة المنطقية في الترحيل إلى false:

AddForeignKey("dbo.Stories", "StatusId", "dbo.Status", "StatusID", cascadeDelete: false);

هي احتمالات ، إذا كنت تقوم بإنشاء علاقات رمي ​​خطأ المحول البرمجي ولكن تريد الحفاظ على حذف شلال؛ لديك مشكلة مع علاقاتك.




أي شخص يتساءل عن كيفية القيام بذلك في جوهر EF:

      protected override void OnModelCreating(ModelBuilder modelBuilder)
            {
                foreach (var relationship in modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys()))
                {
                    relationship.DeleteBehavior = DeleteBehavior.Restrict;
                }
           ..... rest of the code.....



الإجابات الموجودة رائعة أردت فقط أن أضيف أنني واجهت هذا الخطأ بسبب سبب مختلف. أردت إنشاء ترحيل EF أولي على DB موجود ولكن لم أستخدم علامة -IgnoreChanges وتطبيق الأمر Update-Database على قاعدة بيانات فارغة (أيضاً على فشل القائمة).

بدلاً من ذلك ، اضطررت إلى تشغيل هذا الأمر عندما تكون بنية db الحالية هي البنية الحالية:

Add-Migration Initial -IgnoreChanges

هناك على الأرجح مشكلة حقيقية في هيكل ديسيبل ولكن حفظ العالم خطوة واحدة في وقت ...




في .NET Core لعبت مع جميع الإجابات العليا - ولكن دون أي نجاح. لقد أجريت تغييرات كثيرة في بنية DB وفي كل مرة تمت إضافة ترحيل جديد يحاول update-database ، ولكنه تلقى نفس الخطأ.

بعد ذلك ، بدأت في remove-migration واحدا تلو الآخر حتى ألقتني "وحدة التحكم في إدارة الحزم" :

تم تطبيق الترحيل '20170827183131 _ ***' بالفعل على قاعدة البيانات

بعد ذلك ، أضفت ترحيل جديد ( add-migration ) update-database بنجاح

لذلك سيكون اقتراحي: مسح جميع عمليات الترحيل المؤقت ، حتى حالة DB الحالية.




لم يعمل أي من الحلول المذكورة أعلاه بالنسبة لي. ما كان عليّ فعله هو استخدام int int () int () على المفتاح الخارجي الذي لم يكن مطلوبًا (أو ليس مفتاحًا عامودًا غير فارغ) ثم حذف بعض عمليات الترحيل الخاصة بي.

ابدأ بحذف عمليات الترحيل ، ثم جرِّب int inteal.

كانت المشكلة على حد سواء تعديل وتصميم النموذج. كان لا تغيير رمز ضروري.