实体框架代码第一类,父类和子类与其自己的类相同 [英] Entity Framework Code First Class with parent and children of same type as it's own class

查看:90
本文介绍了实体框架代码第一类,父类和子类与其自己的类相同的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我基本上想要一个链接表作为ChildContentRelationship,其中的ParentContent和childContent为Id,Content类将包含一个ChildContentRelationship列表。



造成了很多错误。



这里是我想要做的

  public class Content 
{
public int Id {get;组; }

public int? ParentContentId {get;组; }
public virtual Content ParentContent {get;组; }

public string Name {get;组; }

public int ContentTypeId {get;组; }
public virtual ContentType ContentType {get;组; }

public virtual ICollection< Property>属性{get;组; }

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

我将如何在EF中设置?

解决方案

我不知道我是否正确理解你的模型。我们来讨论一下这些选项。



稍后我省略了这个附加实体 ChildContentRelationship ,我假设 ChildContent 集合的类型为 ICollection< Content>




  • 选项1:



    我假设 ParentContent / strong> ChildContent 。这意味着如果您有内容 Id = x,并且此内容有一个 ChildContent Id = y,那么ChildContents ParentContentId 必须始终为x。这只是一个关联, ParentContent ChildContent 是同一关联的端点。



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

      [InverseProperty(ParentContent)] 
    public virtual ICollection< Content> ChildContent {get;组; }

    ...或使用Fluent API:

      modelBuilder.Entity< Content>()
    .HasOptional(c => c.ParentContent)
    .WithMany(c = cChildContent)
    .HasForeignKey(c => c.ParentContentId);

    我认为这不是你想要的(...与...无关......)。考虑重命名导航属性。如果有人读取 Parent ... Child ... 他很有可能假设他们构建了一对导航属性对于相同的关系。


  • 选项2:



    ParentContent 不是 ChildContent 的反向属性,这意味着您实际上有两个独立关系,并且两个关系的第二个端点都不会在您的模型类中公开。



    ParentContent 的映射如下所示:



    < pre class =lang-cs prettyprint-override> modelBuilder.Entity< Content>()
    .HasOptional(c => c.ParentContent)
    .WithMany()
    .HasForeignKey(c => c.ParentContentId);

    WithMany() without parameters表示第二个端点不是您的模型类中的属性,特别是 ChildContent



    现在,问题是: ChildContent 属于什么样的关系?这是一对多还是多对多的关系?




    • 选项2a



      如果内容指的是其他 ChildContent ,那么作为第二个内容,它将引用相同的 ChildContent s(的内容 ,可以这么说)那么你有一对多的关系。 (这类似于订单和订单项之间的关系:订单项只能属于一个特定订单。)



      ChildContent 将如下所示:

        modelBuilder.Entity< Content> ()
      .HasMany(c => c.ChildContent)
      .WithOptional(); //或WithRequired()

      您将在内容表中数据库属于此关联,但在实体类中没有相应的FK属性。


    • 选项2b



      如果许多内容可以引用相同的 ChildContent

      code> 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 RelationshipType 或...),您将必须引入一个新的实体 ChildContentRelationship 到您的模型中:

        public ChildContentRelationship类
      {
      [Key,Column(Order = 0)]
      public int ParentId {get;组; }
      [Key,Column(Order = 1)]
      public int ChildId {get;组; }

      public Content Parent {get;组; }
      public Content Child {get;组; }

      public DateTime CreationDate {get;组; }
      public string RelationshipType {get;组; }
      }

      现在您的内容 class将收集 ChildContentRelationship s:

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

      而且你有两个一对多的关系: p>

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

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





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


I have a class of Content which should be able to have a parentId for inheritance but also I want it to have a list of child content which is nothing to do with this inheritance tree.

I basically wanted a link table as ChildContentRelationship with Id's for parentContent and childContent in it and the Content class would have a list of ChildContentRelationship.

This has caused a lot of errors.

Here's waht I sort of want to do

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; } 
}

How would I set this up in EF?

解决方案

I am not sure if I understand your model correctly. Let's discuss the options.

For a moment I omit this additional entity ChildContentRelationship and I assume the ChildContent collection is of type ICollection<Content>.

  • Option 1:

    I assume that ParentContent is the inverse property of ChildContent. It would mean that if you have a Content with Id = x and this Content has a ChildContent with Id = y then the ChildContents ParentContentId must always be x. This would only be a single association and ParentContent and ChildContent are the endpoints of this same association.

    The mapping for this relationship can be created either with data annotations ...

    [InverseProperty("ParentContent")]
    public virtual ICollection<Content> ChildContent { get; set; }
    

    ... or with Fluent API:

    modelBuilder.Entity<Content>()
        .HasOptional(c => c.ParentContent)
        .WithMany(c => c.ChildContent)
        .HasForeignKey(c => c.ParentContentId);
    

    I think this is not what you want ("...has nothing to do with..."). Consider renaming your navigation properties though. If someone reads Parent... and Child... he will very likely assume they build a pair of navigation properties for the same relationship.

  • Option 2:

    ParentContent is not the inverse property of ChildContent which would mean that you actually have two independent relationships and the second endpoint of both relationships is not exposed in your model class.

    The mapping for ParentContent would look like this:

    modelBuilder.Entity<Content>()
        .HasOptional(c => c.ParentContent)
        .WithMany()
        .HasForeignKey(c => c.ParentContentId);
    

    WithMany() without parameters indicates that the second endpoint is not a property in your model class, especially it is not ChildContent.

    Now, the question remains: What kind of relationship does ChildContent belong to? Is it a one-to-many or is it a many-to-many relationship?

    • Option 2a

      If a Content refers to other ChildContents and there can't be a second Content which would refer to the same ChildContents (the children of a Content are unique, so to speak) then you have a one-to-many relationship. (This is similar to a relationship between an order and order items: An order item can only belong to one specific order.)

      The mapping for ChildContent would look like this:

      modelBuilder.Entity<Content>()
          .HasMany(c => c.ChildContent)
          .WithOptional(); // or WithRequired()
      

      You will have an additional foreign key column in the Content table in your database which belongs to this association but doesn't have a corresponding FK property in the entity class.

    • Option 2b

      If many Contents can refer to the same ChildContents then you have a many-to-many relationship. (This is similar to a relationship between a user and roles: There can be many users within the same role and a user can have many roles.)

      The mapping for ChildContent would look like this:

      modelBuilder.Entity<Content>()
          .HasMany(c => c.ChildContent)
          .WithMany()
          .Map(x =>
          {
              x.MapLeftKey("ParentId");
              x.MapRightKey("ChildId");
              x.ToTable("ChildContentRelationships");
          });
      

      This mapping will create a join table ChildContentRelationships in the database but you don't need a corresponding entity for this table.

    • Option 2c

      Only in the case that the many-to-many relationship has more properties in addition to the two keys (ParentId and ChildId) (for example something like CreationDate or RelationshipType or...) you would have to introduce a new entity ChildContentRelationship into your model:

      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; }
      }
      

      Now your Content class would have a collection of ChildContentRelationships:

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

      And you have two one-to-many relationships:

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

I believe that you want either option 2a or 2b, but I am not sure.

这篇关于实体框架代码第一类,父类和子类与其自己的类相同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆