且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

同一实体的多对多集合,具有双向关系

更新时间:2022-04-19 22:50:49

你需要在小部件内部引入另一个集合,类似的.

You need to introduce another collection inside the widget, something like.

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

默认没有fluent-api配置,这段代码只会在数据库中创建一个WidgetWidgets的容器表,包含Widget_IdWidget_Id1.

By default with no fluent-api configuration, this code only will create a container table of WidgetWidgets in the database that contains two columns Widget_Id and Widget_Id1.

但你需要保持一致,只使用其中一个集合来建立相邻关系.如果你使用 AdjacentTo 集合来建立相邻关系.

But you need to be consistent to only use one of the collection to make an adjacent relationship. If you use AdjacentTo collection to make an adjacent relationship.

widget1.AdjacentTo.Add(widget2);

保存后widget1.AdjacentTo会有widget2widget2.AdjacentFrom会有widget1.p>

After being saved widget1.AdjacentTo will have widget2 and widget2.AdjacentFrom will have widget1.

Widget_Id   Widget_Id1
    2           1

但是如果你再次输入与AdjacentFrom集合建立相邻关系.

But if you input again with AdjacentFrom collection to make an adjacent relationship.

widget1.AdjacentFrom.Add(widget2);

保存后widget1.AdjacentFromwidget1.AdjacentTo会有widget2.widget2 也会发生同样的事情.

After being saved widget1.AdjacentFrom and widget1.AdjacentTo will have widget2. Same thing happens with widget2.

Widget_Id   Widget_Id1
    2           1
    1           2

复合唯一键不能阻止插入第二条记录,因为第二条记录不被视为重复行.但是有一个变通方法是添加一个检查约束,你可以在迁移中添加这个约束.

Composite unique key can't prevent second record to be inserted, because the second record is not considered as duplicate row. But there is a workaround by adding a check constraint, you can add this constraint in the migration.

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

要选择所有相邻的,您可以添加另一个集合,例如.


To select all adjacent you can add another collection, something like.

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

添加检查约束后,您可以使用此扩展来添加或删除相邻的.


After adding check constraint, then you can use this extension to add or remove adjacent.

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