您需要在小部件中引入另一个集合,例如。
public virtual ICollection<Widget> AdjacentFrom { get; set; }
public virtual ICollection<Widget> AdjacentTo { get; set; }
默认没有fluent-api配置,这段代码只会在数据库中创建一个WidgetWidgets的容器表,包含Widget_Id和Widget_Id1两列。
但你需要保持一致,只使用其中一个集合来建立相邻关系。如果你使用AdjacentTo集合来建立相邻关系。
widget1.AdjacentTo.Add(widget2);
保存后widget1.AdjacentTo 将有widget2 和widget2.AdjacentFrom 将有widget1。
Widget_Id Widget_Id1
2 1
但如果你再次输入与AdjacentFrom集合建立相邻关系。
widget1.AdjacentFrom.Add(widget2);
保存后widget1.AdjacentFrom 和widget1.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);
}
}
}