我正在尝试使用代码优先实体框架,在名为Sector
和Ship
的两个类之间建立简单的双向关系。这里的想法是Sector
可以有0到多Ships
,其中Ship
始终有Sector
,它是当前位置。
出于导航目的,我想在关系的两边都有一个属性。因此,类Sector
包含ICollection<Ship>
类型的属性,其中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 });
}
表中的结果:
Sector
- X
- Y
Ship
- ID
- Name
- Speed
- Sector_X
- Sector_Y
问题在于,只要我在Ship
和Sector
之间建立另一种关系,即它是Destination
,就会在双方使用外键创建前面提到的关系。首先,我想知道为什么,其次如何防止它出现问题?我没有看到需要,并且导致第一个关系无法从双方导航,因为Sector_X
和Sector_Y
是NULL
或Sector_X1
和{{1是Sector_Y1
。代表同样的事情。
NULL
答案 0 :(得分:1)
添加Destination
媒体资源时,您还需要在Sector
班级IncomingShips
上添加导航集。或者不要在Sector
类上添加任何导航集。
我假设EF在Ship
到Sector
有2个导航属性但在Ship
中只有一个Sector
集合时会感到困惑,因此它会继续创建3 FK对
使用:
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
答案 1 :(得分:0)
如果你看下&#34;关系公约&#34;在Code First Conventions,它说
如果相同类型之间存在多个关系(例如,假设您定义Person和Book类,其中Person类包含CommentsBooks和AuthoredBooks导航属性,而Book类包含Author和Reviewer导航属性),则需要通过使用Data Annotations或流畅的API手动配置关系。
由于componentWillReceiveProps
和Ship
之间存在多个关系,因此EF无法确定Sector
上哪个导航属性与Ship
上的集合属性相反,并创建了Sector
的单独关系。
您需要使用Data Annotations(此处为一个示例,但还有其他方法可以执行此操作):
Sector.Ships
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();
}
与Sector
有多个1:多关系,因此您可能必须使用Fluent API,因为您需要将至少一个关系设置为默认情况下不级联删除(或将Ship
设置为可选?)或者您将获得&#34;多个级联路径&#34;错误。