回答

收藏

父级和子级与自己的类具有相同类型的实体框架代码第一类

技术问答 技术问答 309 人阅读 | 0 人回复 | 2023-09-14

我有一类Content,应该能够具有用于继承的parentId,但我也希望它具有与该继承树无关的子内容列表。
$ w9 e. t  P3 o7 _: x我基本上想要一个链接表作为ChildContentRelationship,在其中具有id的parentContent和childContent,并且Content类将具有ChildContentRelationship的列表。
/ V) y6 O% {+ @' ^; P6 v4 z这导致了很多错误。
9 y" m0 U; z9 D$ x- k. t这是我想做的; g$ x; c* A0 D' J; }; v; s2 q
public class Content
* ]# y- ?$ U: U+ J3 r, F: x( z8 K{
/ k$ U* _6 c) c1 R. \) X; h# \    public int Id { get; set; }
# ~  n# y# G* M, [/ l8 Y    public int? ParentContentId { get; set; }
# f% h9 p2 t- k    public virtual Content ParentContent { get; set; }# Z1 x1 Y" B/ ^' N: ^- u. i, ~
    public string Name { get; set; }
( n& ]( ^' v, k( Y2 |    public int ContentTypeId { get; set; }$ D/ V! q7 @! J9 b  }
    public virtual ContentType ContentType { get; set; }
0 c1 h' O# N9 ^9 y+ K. m    public virtual ICollection Properties { get; set; }
' v8 Y5 h4 Y  s, I    public virtual ICollection ChildContent { get; set; } # [9 z8 \2 i. n  d
}
$ H5 b$ R: v: `# }我将如何在EF中进行设置?* ~5 O7 K! b9 N6 J1 f
               
# Z4 F% Z& h8 O8 R! d% A解决方案:
5 |% f2 a% ]  S( h) D                  i# e0 S6 Q! n
9 W. \* u' k! Q: z6 e
& A* s9 U: t5 a0 C( ?! z: j- I% K& i
                我不确定我是否正确理解您的模型。让我们讨论一下这些选项。
" N! z$ L. N* K8 \, @3 S% T( ?一会儿,我忽略了这个额外的实体,ChildContentRelationship并假设该ChildContent集合是type
& {+ G0 }. }* wICollection。
  l4 u8 H: O# l1 h& z选项1:2 I4 n9 s! d. \6 C
6 H" z3 A2 Y' \
我认为ParentContent是 逆属性 的ChildContent。这意味着如果您有一个Contentwith Id=/ Y* o8 O# W. d& I# f( ^
x,而此Content有一个ChildContentwith Id=4 D. L5 ?" Q% E! ]- R; F2 T- N
y,则ChildContentsParentContentId必须始终为x。这仅是单个关联,ParentContent并且ChildContent是该相同关联的端点。$ }$ p% ^. t2 k# n4 M/ {
可以使用数据注释创建此关系的映射…
% l! v6 N$ L! X# r- y2 Y    [InverseProperty(&quotarentContent")]
0 t$ V6 e; D# K# I$ I- L% L9 A* f+ p7 \public virtual ICollection ChildContent { get; set; }
& Q( U, Y4 y. g4 ^…或使用Fluent API:9 `, v9 H( _2 u& @& H2 {
    modelBuilder.Entity()5 B8 u8 i4 q7 y; H# `
    .HasOptional(c => c.ParentContent)
+ A7 E) q/ H" U0 \; c    .WithMany(c => c.ChildContent); p2 F1 l$ y- Y4 _& z* E
    .HasForeignKey(c => c.ParentContentId);
3 E1 b" a7 l: Y我认为这不是您想要的( “ …与…无关”2 R# @$ a! a! h3 [
)。不过,请考虑重命名导航属性。如果有人阅读Parent...并且Child...他很可能会假设他们为相同的关系建立了一对导航属性。
$ H: \, ?0 h% j2 P选项2:
8 A' a( J5 P: ?" h8 y# h1 |- }
5 t. E5 k, w, L! D/ A1 D8 o" W
ParentContent不是它的inverse属性,ChildContent这意味着您实际上有两个独立的关系,并且两个关系的第二个端点都没有在模型类中公开。
% v. l8 [6 F6 s2 }6 m的映射ParentContent如下所示:
) f& ]# O" a0 b5 C    modelBuilder.Entity()
; e5 ?: ^+ w* _0 _" y/ g    .HasOptional(c => c.ParentContent)6 J$ t, |) }1 N
    .WithMany()7 O% P5 P+ y/ O! N
    .HasForeignKey(c => c.ParentContentId);5 f8 y1 y; ?1 F2 J. M# Y
WithMany()没有参数表示第二个端点不是模型类中的属性,尤其是 不是 ChildContent。
/ x4 `; ]$ x/ o3 k现在,问题仍然存在:ChildContent属于哪种关系?是一对多关系还是多对多关系?
% s* T1 B. l2 R( N2 M7 M* 选项2a
- Z* k0 U; G9 j" I' L  ]4 X! O如果aContent引用其他ChildContents并且不能有第二个Content引用相同的ChildContents(a的子代Content是2 i0 S) q1 ~. `. H
唯一的 ,可以这么说),那么您就有一对多的关系。(这类似于订单和订单商品之间的关系:一个订单商品只能属于一个特定的订单。)' z1 w: k) u- H$ j' c
的映射ChildContent如下所示:
' G5 p, G5 v' f/ W4 L0 d  ?/ s            modelBuilder.Entity()& e2 d& P7 F4 {- h+ ]
        .HasMany(c => c.ChildContent)
6 R/ h$ g+ p/ t+ o) H4 V6 Y        .WithOptional(); // or WithRequired()
4 w" @. `5 H: Y, A& c' T' J, E- V您Content的数据库表中将具有一个附加的外键列,该列属于该关联,但在实体类中没有对应的FK属性。% o% C# y$ V. @, y4 x9 n+ J8 t
* 选项2b; x- B0 a' H2 C; e
如果许多Content可以引用相同ChildContent的,则您具有多对多关系。(这类似于用户和角色之间的关系:同一角色中可以有许多用户,并且一个用户可以有许多角色。)
5 o% J8 z* J$ G2 q* H# r的映射ChildContent如下所示:
7 [& }& d1 W% e/ X0 R            modelBuilder.Entity()
6 O' C5 Y* l- F1 u        .HasMany(c => c.ChildContent). C- H6 ?: V) g, @4 U- g" _. O
        .WithMany()
2 v" P! y* L& ?( M0 h        .Map(x =>0 `* D# M9 ^6 O2 L- R
        {
! U( \/ @. F  U5 I. G3 d! w/ @& I3 }            x.MapLeftKey(&quotarentId");
, O* F5 v7 z  a, y8 c/ p            x.MapRightKey("ChildId");
; B' T+ C/ j$ D8 {            x.ToTable("ChildContentRelationships");
" }* j! l9 A" x+ W        });7 X% @7 ]0 e7 n" c. \
该映射将ChildContentRelationships在数据库中创建一个联接表,但此表不需要相应的实体。
8 N- \. I- A( D+ ~" f* 选项2c  S  H& w8 I) g4 g) I8 d7 O/ q! E! Z
仅在多对多关系除了两个键(ParentId和ChildId)之外具有更多属性的情况下(例如,诸如CreationDateorRelationshipType或…),您才需要ChildContentRelationship在模型中引入一个新实体:# X% _. }3 n" f7 y$ n: y
            public class ChildContentRelationship
$ g/ n  I) D7 e& o  n" P8 A    {7 F+ k! e3 N8 ~% T
        [Key, Column(Order = 0)]& a1 K3 U& X' j- M
        public int ParentId { get; set; }7 X! z% \" P2 E7 Q
        [Key, Column(Order = 1)]
8 ?$ a( U  ~' h, z9 a/ H- Y- T8 z        public int ChildId { get; set; }
! h# z" |  C' |        public Content Parent { get; set; }# m! @! r/ }; Z% k2 [
        public Content Child { get; set; }" U  X: o: Q/ i( k( L8 c
        public DateTime CreationDate { get; set; }- O7 I6 H$ J' B# @
        public string RelationshipType { get; set; }
& O0 M5 T$ j' q3 o( G* o    }4 j. M. c& ?: }$ i
现在您的Content班级将有ChildContentRelationships的集合:: Z& K; O, `; c0 P3 r+ _
            public virtual ICollection ChildContent
5 L- `6 e4 Y5 D, |/ G2 S2 |        { get; set; }( ]% k4 M' e, Y/ L# ^. b4 e
您有 两个 一对多的关系:; f3 y" [/ |( s4 f+ x. ~
            modelBuilder.Entity()
* p5 ]0 x* ^% g: E% T3 r4 T        .HasRequired(ccr => ccr.Parent)7 K9 H3 p+ z9 k- l
        .WithMany(c => c.ChildContent)
  {* `7 c9 F$ t' D( e        .HasForeignKey(ccr => ccr.ParentId);6 ~: V) h& l3 j0 w7 w
    modelBuilder.Entity()2 }: S( M' Y* u
        .HasRequired(ccr => ccr.Child)! Y  H9 }; e+ I+ Z- Y
        .WithMany()
& r5 z% X9 R; Y5 {        .HasForeignKey(ccr => ccr.ChildId);
: H1 x! @7 b; v我相信您想要选项2a或2b,但是我不确定。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则