我有一类Content,应该能够具有用于继承的parentId,但我也希望它具有与该继承树无关的子内容列表。

我基本上想要一个链接表作为ChildContentRelationship,在其中具有id的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中进行设置?

最佳答案

我不确定我是否正确理解您的模型。让我们讨论选项。

有一会儿我忽略了这个额外的实体ChildContentRelationship,并且我假定ChildContent集合的类型为ICollection<Content>


选项1:

我假设ParentContentChildContent的逆属性。这意味着,如果您具有Content = x的Id,并且此内容具有ChildContent = y的Id,则ChildContents ParentContentId必须始终为x。这仅是单个关联,并且ParentContentChildContent是同一关联的端点。

可以使用数据注释创建此关系的映射...

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


我认为这不是您想要的(“ ...与...无关”)。不过,请考虑重命名导航属性。如果有人阅读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

仅在多对多关系除了两个键(ParentIdChildId)(例如CreationDateRelationshipType或...之类)具有更多属性的情况下,将新的实体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类将具有ChildContentRelationship的集合:

public virtual ICollection<ChildContentRelationship> ChildContent
    { get; set; }


您有两个一对多的关系:

modelBuilder.Entity<ChildContentRelationship>()
    .HasRequired(ccr => ccr.Parent)
    .WithMany(c => c.ChildContent)
    .HasForeignKey(ccr => ccr.ParentId);

modelBuilder.Entity<ChildContentRelationship>()
    .HasRequired(ccr => ccr.Child)
    .WithMany()
    .HasForeignKey(ccr => ccr.ChildId);




我相信您想要选项2a或2b,但是我不确定。

09-27 06:55