簡體   English   中英

同一實體的多對多集合,具有雙向關系

[英]Many-to-many collection of same entity, with two-way relationship

假設我有一個小部件實體,並且我想跟蹤與每個小部件相鄰的其他小部件。 如果第一個窗口小部件與第二個窗口小部件相鄰,則倒數也適用-第二個窗口小部件與第一個窗口小部件相鄰。

理想情況下,我在實體上只有一個集合,並且可以為這種關系流暢地配置實體。

public class Widget
{
    // ...

    public virtual ICollection<Widget> Adjacent { get; set; }
}

但是,當我嘗試...

modelBuilder.Entity<Widget>
            .HasMany(w => w.Adjacent)
            .WithMany(w => w.Adjacent);

...實體框架根本不喜歡它。

在類型“小部件”上聲明的導航屬性“相鄰”不能與其本身相反。

有沒有一種方法可以配置實現此目標的實體,還是我將被困於創建父/子集合導航屬性或單獨的關系容器?

您需要在小部件內引入另一個類似的集合。

public virtual ICollection<Widget> AdjacentFrom { get; set; }
public virtual ICollection<Widget> AdjacentTo { get; set; }

默認情況下,沒有fluent-api配置,此代碼只會在數據庫中創建WidgetWidgets的容器表,該表包含兩列Widget_IdWidget_Id1


但是您需要保持一致,僅使用集合之一建立相鄰關系。 如果使用AdjacentTo集合來建立相鄰關系。

widget1.AdjacentTo.Add(widget2);

保存后, widget1.AdjacentTo將具有widget2widget2.AdjacentFrom將具有widget1

Widget_Id   Widget_Id1
    2           1

但是如果您再次使用AdjacentFrom集合輸入來建立相鄰關系。

widget1.AdjacentFrom.Add(widget2);

保存后, widget1.AdjacentFromwidget1.AdjacentTo將具有widget2 相同的事情發生在widget2

Widget_Id   Widget_Id1
    2           1
    1           2

復合唯一鍵無法阻止插入第二條記錄,因為第二條記錄不被視為重復行。 但是有一種解決方法,即添加檢查約束,您可以在遷移中添加此約束。

Sql("alter table WidgetWidgets add constraint CK_Duplicate_Widget check (Widget_Id > Widget_Id1)");

要選擇所有相鄰對象,您可以添加另一個集合,例如。

[NotMapped]
public ICollection<Widget> Adjacent
{
   get { return (AdjacentFrom ?? new Widget[0]).Union((AdjacentTo ?? new Widget[0])).Distinct().ToArray(); }
}

添加檢查約束后,您可以使用此擴展名添加或刪除相鄰項。

public static class WidgetDbExtension
{
    public static void AddAdjacent(this Widget widget1, Widget widget2)
    {
        if (widget1.Id < widget2.Id)
        {
            widget1.AdjacentTo.Add(widget2);
        }
        else
        {
            widget2.AdjacentTo.Add(widget1);
        }
    }
    public static void RemoveAdjacent(this Widget widget1, Widget widget2)
    {
        if (widget1.Id < widget2.Id)
        {
            widget1.AdjacentTo.Remove(widget2);
        }
        else
        {
            widget2.AdjacentTo.Remove(widget1);
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM