多对多个相同的实体的集合,具有双向关系 [英] Many-to-many collection of same entity, with two-way relationship

查看:153
本文介绍了多对多个相同的实体的集合,具有双向关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个小部件的实体,我要跟踪其他部件是相邻的。如果第一小部件是靠近第二小部件,则该逆也是如此—二是邻近第一

Suppose I have a widget entity, and I want to track other widgets that are adjacent to each. If the first widget is adjacent to the second widget, then the inverse is also true—the second is adjacent to the first.

在理想情况下,我会对实体单个集合,并能流利地配置实体这样的一个关系。

Ideally, I would have a single collection on the entity, and could fluently configure the entity for this sort of a relationship.

public class Widget
{
    // ...

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

然而,当我尝试......

However, when I try that...

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

...实体框架不喜欢它。

...Entity Framework doesn't like it at all.

导航属性'邻'的类型窗口小部件声明不可能是它自身的逆。

The navigation property 'Adjacent' declared on type 'Widget' cannot be the inverse of itself.

有没有一种方法来配置,可实现这一目标的实体,还是我将要陷入创建父/子集导航属性或独立关系的容器?

Is there a way to configure the entity that achieves this goal, or am I going to be stuck creating parent/child collection navigation properties or separate relationship containers?

推荐答案

您需要引入另一个集合小部件里面,有点像。

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

默认情况下,没有流畅-API配置,这code只会在包含两列 WidgetWidgets 的容器表> Widget_Id 和 Widget_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 widget2 widget2.AdjacentFrom 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.AdjacentFrom widget1.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

复合唯一键不能prevent第二个记录被插入,因为第二个记录不被视为重复的行。但是有一个解决方法通过增加一个检查约束,您可以在迁移中添加此约束。

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

这篇关于多对多个相同的实体的集合,具有双向关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆