实体框架代码第一类,父类和子类与其自己的类相同 [英] Entity Framework Code First Class with parent and children of same type as it's own class
问题描述
我基本上想要一个链接表作为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,那么ChildContentsParentContentId
必须始终为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 $ c那么你会有多对多的关系。 (这与用户和角色之间的关系类似:同一个角色中可以有很多用户,用户可以有很多角色。)
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 ofChildContent
. It would mean that if you have aContent
withId
= x and this Content has aChildContent
withId
= y then the ChildContentsParentContentId
must always be x. This would only be a single association andParentContent
andChildContent
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...
andChild...
he will very likely assume they build a pair of navigation properties for the same relationship.Option 2:
ParentContent
is not the inverse property ofChildContent
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 notChildContent
.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 otherChildContent
s and there can't be a secondContent
which would refer to the sameChildContent
s (the children of aContent
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
Content
s can refer to the sameChildContent
s 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
andChildId
) (for example something likeCreationDate
orRelationshipType
or...) you would have to introduce a new entityChildContentRelationship
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 ofChildContentRelationship
s: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屋!