我有一类Content,它应该能够有一个parentId用于继承,但我希望它有一个子内容列表,这与这个继承树无关。
我基本上想要一个链接表作为ChildContentRelationship,其中包含parentContent和childContent的Id,而Content类将有一个ChildContentRelationship列表。
这导致了很多错误。
这是我想做的事情
public class Content
{
public int Id { get; set; }
public int? ParentContentId { get; set; }
public virtual Content ParentContent { get; set; }
public string Name { get; set; }
public int ContentTypeId { get; set; }
public virtual ContentType ContentType { get; set; }
public virtual ICollection<Property> Properties { get; set; }
public virtual ICollection<ChildContentRelationship> ChildContent { get; set; }
}
我如何在EF中设置它?
答案 0 :(得分:18)
我不确定我是否正确理解您的模型。我们来讨论一下这些选项。
暂时我省略了这个额外的实体ChildContentRelationship
,我认为ChildContent
集合的类型为ICollection<Content>
。
选项1:
我认为ParentContent
是ChildContent
的反向属性。这意味着,如果您的Content
Id
= x且此内容的ChildContent
为Id
= y,那么ChildContents ParentContentId
必须始终为X。这只是一个关联,ParentContent
和ChildContent
是同一关联的终点。
可以使用数据注释创建此关系的映射...
[InverseProperty("ParentContent")]
public virtual ICollection<Content> ChildContent { get; set; }
...或使用Fluent API:
modelBuilder.Entity<Content>()
.HasOptional(c => c.ParentContent)
.WithMany(c => c.ChildContent)
.HasForeignKey(c => c.ParentContentId);
我认为这不是你想要的(&#34; ......与...无关&#34; )。考虑重命名导航属性。如果有人阅读Parent...
和Child...
,他很可能会假设他们为同一关系构建了一对导航属性。
选项2:
ParentContent
不是ChildContent
的反向属性,这意味着您实际上有两个独立的关系,并且两个关系的第二个端点都没有在您的模型类中公开。
ParentContent
的映射如下所示:
modelBuilder.Entity<Content>()
.HasOptional(c => c.ParentContent)
.WithMany()
.HasForeignKey(c => c.ParentContentId);
不带参数的 WithMany()
表示第二个端点不是模型类中的属性,尤其是不是 ChildContent
。
现在,问题仍然存在:ChildContent
属于什么样的关系?它是一对多还是多对多的关系?
选项2a
如果Content
引用其他ChildContent
并且不能成为第二个Content
,则会引用相同的ChildContent
(一个Content
唯一,可以这么说)那么你就有了一对多的关系。 (这类似于订单和订单商品之间的关系:订单商品只能属于一个特定订单。)
ChildContent
的映射如下所示:
modelBuilder.Entity<Content>()
.HasMany(c => c.ChildContent)
.WithOptional(); // or WithRequired()
在数据库的Content
表中,您将拥有一个额外的外键列,该列属于此关联,但在实体类中没有相应的FK属性。
选项2b
如果许多Content
可以引用相同的ChildContent
,那么您就拥有多对多的关系。 (这类似于用户和角色之间的关系:同一角色中可以有许多用户,用户可以拥有多个角色。)
ChildContent
的映射如下所示:
modelBuilder.Entity<Content>()
.HasMany(c => c.ChildContent)
.WithMany()
.Map(x =>
{
x.MapLeftKey("ParentId");
x.MapRightKey("ChildId");
x.ToTable("ChildContentRelationships");
});
此映射将在数据库中创建联接表ChildContentRelationships
,但您不需要此表的相应实体。
选项2c
仅在多对多关系除了两个键(ParentId
和ChildId
)之外还有更多属性的情况下(例如CreationDate
或{{ 1}}或...)您必须在模型中引入新的实体RelationshipType
:
ChildContentRelationship
现在,您的public class ChildContentRelationship
{
[Key, Column(Order = 0)]
public int ParentId { get; set; }
[Key, Column(Order = 1)]
public int ChildId { get; set; }
public Content Parent { get; set; }
public Content Child { get; set; }
public DateTime CreationDate { get; set; }
public string RelationshipType { get; set; }
}
课程将收集Content
s:
ChildContentRelationship
你有两个一对多的关系:
public virtual ICollection<ChildContentRelationship> ChildContent
{ get; set; }
我相信您需要选项2a或2b,但我不确定。