C# 如何让双向关系在添加另一个关系时不在两侧创建外键?
我试图使用代码优先实体框架在名为C# 如何让双向关系在添加另一个关系时不在两侧创建外键?,c#,entity-framework,C#,Entity Framework,我试图使用代码优先实体框架在名为Sector和Ship的两个类之间建立一个简单的双向关系。这里的想法是扇区可以有零到多个船舶,其中船舶始终有一个扇区,它是当前位置 出于导航目的,我希望在关系的两边都有一个属性。因此,classSector包含类型为ICollection的属性,其中Ship包含类型为Sector的属性 Sector的主键是X和Y的组合 public class Ship { public int ID { get; set; } public string Nam
Sector
和Ship
的两个类之间建立一个简单的双向关系。这里的想法是扇区
可以有零到多个船舶
,其中船舶
始终有一个扇区
,它是当前位置
出于导航目的,我希望在关系的两边都有一个属性。因此,classSector
包含类型为ICollection
的属性,其中Ship
包含类型为Sector
的属性
Sector
的主键是X
和Y
的组合
public class Ship
{
public int ID { get; set; }
public string Name { get; set; }
public double Speed { get; set; }
public virtual Sector Sector { get; set; }
//public virtual Sector Destination { get; set; }
}
public class Sector
{
public Int64 X { get; set; }
public Int64 Y { get; set; }
public virtual ICollection<Ship> Ships { get; set; }
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
// combined key for sector
modelBuilder.Entity<Sector>()
.HasKey(s => new { s.X, s.Y });
}
问题是,只要我在船舶
和扇区
之间建立另一个关系,即它的目的地
,前面提到的关系就会在两侧用外键创建。首先,我想知道为什么,其次,如何防止它发生?我不认为有必要,这导致第一个关系不能从两侧导航,因为扇区X
和扇区Y
都是NULL
或扇区X1
和扇区Y1
都是NULL
。它们代表相同的东西
Sector
- X
- Y
Ship
- ID
- Name
- Speed
- Sector_X
- Sector_Y
- Destination_X
- Destination_Y
- Sector_X1
- Sector_X2
添加
目的地
属性时,您还需要在扇区
类中包括导航集合,例如收入船舶
。或者不要在扇区
类上添加任何导航集合
我假设当有两个导航属性从Ship
到Sector
时,EF会感到困惑,但是Sector
中只有一个Ship
集合,所以它会继续创建3个FK对
使用:
--或--
如果你在“关系约定”下查看,它会说
如果相同类型之间存在多个关系(例如,假设您定义了Person和Book类,其中Person类包含ReviewBooks和AuthoredBooks导航属性,Book类包含Author和Reviewer导航属性)您需要使用数据注释或fluent API手动配置关系
由于船舶
和扇区
之间存在多个关系,EF无法确定船舶
上的哪个导航属性与扇区
上的集合属性相反,并为扇区.Ships
创建单独的关系
您需要使用(这里有一个示例,但还有其他方法):
公营部门
{
公共Int64 X{get;set;}
公共Int64 Y{get;set;}
[反向财产(“部门”)]
公共虚拟ICollection{get;set;}
}
或:
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
//其他东西。。。
modelBuilder.Entity()
.HasRequired(p=>p.Sector)
.有许多(p=>p.Ships);
modelBuilder.Entity()
.HasRequired(p=>p.Destination)
.有很多
.WillCascadeOnDelete();
}
由于
扇区
与配送
有多个1:many关系,您可能必须使用Fluent API,因为您需要将至少一个关系设置为默认情况下不级联删除(或将配送目的地
设置为可选),或者您将获得“多个级联路径”错误。我认为EF可能会感到困惑,因为它不知道Sector.Ships
是否是Ship.Sector
或Ship.Destination
的反义词,因为这对我来说似乎很有用。然而,正是jjj的回答让我理解了围绕我的问题的“为什么”。在你们两人之间,你们设法帮助了我,我相信他的答案应该是被接受的,仅仅是因为参考的理论背景。不过我还是非常感谢你的加入+1.
Sector
- X
- Y
Ship
- ID
- Name
- Speed
- Sector_X
- Sector_Y
- Destination_X
- Destination_Y
- Sector_X1
- Sector_X2
public class Ship {
public int ID { get; set; }
public string Name { get; set; }
public double Speed { get; set; }
public virtual Sector Sector { get; set; }
public virtual Sector Destination { get; set; }
}
public class Sector {
public Int64 X { get; set; }
public Int64 Y { get; set; }
}
public class Ship {
public int ID { get; set; }
public string Name { get; set; }
public double Speed { get; set; }
public virtual Sector Sector { get; set; }
public virtual Sector Destination { get; set; }
}
public class Sector {
public Int64 X { get; set; }
public Int64 Y { get; set; }
public virtual ICollection<Ship> Ships { get; set; }
public virtual ICollection<Ship> IncomingShips { get; set; }
}
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
.....
modelBuilder.Entity<Sector>()
.HasMany(p => p.Ships)
.WithRequired(p => p.Sector)
.WillCascadeOnDelete(false);
modelBuilder.Entity<Sector>()
.HasMany(p => p.IncomingShips)
.WithRequired(p => p.Destination)
.WillCascadeOnDelete(false);
}
Sector
- X
- Y
Ship
- ID
- Name
- Speed
- Sector_X
- Sector_Y
- Destination_X
- Destination_Y
public class Sector
{
public Int64 X { get; set; }
public Int64 Y { get; set; }
[InverseProperty("Sector")]
public virtual ICollection<Ship> Ships { get; set; }
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// other stuff...
modelBuilder.Entity<Ship>()
.HasRequired(p => p.Sector)
.WithMany(p => p.Ships);
modelBuilder.Entity<Ship>()
.HasRequired(p => p.Destination)
.WithMany()
.WillCascadeOnDelete();
}