回答

收藏

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

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

我有一类Content,应该能够具有用于继承的parentId,但我也希望它具有与该继承树无关的子内容列表。
& o& c3 ]  d4 V8 `3 V, A我基本上想要一个链接表作为ChildContentRelationship,在其中具有id的parentContent和childContent,并且Content类将具有ChildContentRelationship的列表。
! F5 }; i8 |8 |& X" y+ r3 b' y2 M这导致了很多错误。9 h# @" W' j, i( V. H
这是我想做的, K2 I/ ~! Q5 D, R
public class Content6 S: \2 }) U1 P
{. j0 \. ~1 O5 C9 f
    public int Id { get; set; }, n' U" A+ R( Y
    public int? ParentContentId { get; set; }
/ b% J  f) T( Y& D    public virtual Content ParentContent { get; set; }# t8 l( T$ P% X& [
    public string Name { get; set; }
$ H7 l% z& O+ s. E    public int ContentTypeId { get; set; }
5 G: b" S2 _5 D/ L    public virtual ContentType ContentType { get; set; }$ s; P, k6 Q0 q+ |+ d  A
    public virtual ICollection Properties { get; set; }
3 P0 E% E8 y) r" {    public virtual ICollection ChildContent { get; set; }
( e0 X% S+ N, `& l; V+ g}
/ h6 ^' D7 ^, H; g% Z! D$ E我将如何在EF中进行设置?' [& J: p  F% P6 v0 s9 V
               
8 F3 q& h+ J6 z! @% y解决方案:5 K6 ?- j2 V' j7 ^* V
                ; `9 B1 o; Z2 s+ p& p
- N: i: c  g+ }9 C( _( I1 v

4 m* W8 A; ~  F                我不确定我是否正确理解您的模型。让我们讨论一下这些选项。
0 ]! y# f) Y' d$ V0 I3 T7 y: S一会儿,我忽略了这个额外的实体,ChildContentRelationship并假设该ChildContent集合是type6 C) o7 b+ v& h2 C/ J: Y( t, z/ Y4 O
ICollection。8 c0 |$ O' i$ |* t1 P3 G
选项1:
9 n4 D0 j0 c: _. s) y' f7 p, t

! {( H( R3 K1 C8 Y我认为ParentContent是 逆属性 的ChildContent。这意味着如果您有一个Contentwith Id=
/ {. @; u& a- E2 a: @0 Hx,而此Content有一个ChildContentwith Id=
" z  }6 C6 _* l' O3 qy,则ChildContentsParentContentId必须始终为x。这仅是单个关联,ParentContent并且ChildContent是该相同关联的端点。
  `3 [( l$ N7 i% i' J. H' O可以使用数据注释创建此关系的映射…
: F: o) Y" ]9 i3 B: p; A, x2 h    [InverseProperty(&quotarentContent")]- p& r5 ^4 U: z  r5 M& l) L3 h! C
public virtual ICollection ChildContent { get; set; }
2 H; u9 k; D( A8 p…或使用Fluent API:) ]5 w4 n  [3 E% j- e- g! H$ s! f
    modelBuilder.Entity()
( J4 P9 H- `' `' ~6 k    .HasOptional(c => c.ParentContent)
1 q- \* l. h2 L! b2 @    .WithMany(c => c.ChildContent)6 y* H# L1 h2 ?+ W$ E$ k8 o
    .HasForeignKey(c => c.ParentContentId);
- H1 y! I, Q8 q7 T9 w我认为这不是您想要的( “ …与…无关”$ M# p7 d' ?7 E% D  T7 H
)。不过,请考虑重命名导航属性。如果有人阅读Parent...并且Child...他很可能会假设他们为相同的关系建立了一对导航属性。; @1 X9 x8 u0 ^) Y$ M
选项2:9 g/ O5 K( v, T% J) U
9 g4 H" I5 l9 c( Y2 o
ParentContent不是它的inverse属性,ChildContent这意味着您实际上有两个独立的关系,并且两个关系的第二个端点都没有在模型类中公开。$ l/ O( ]/ ?' r; V
的映射ParentContent如下所示:7 }( ?! C( W6 l7 x( c: J
    modelBuilder.Entity()
1 m. E# O9 T! M* H    .HasOptional(c => c.ParentContent)
7 p( K- m; o2 s& t- K    .WithMany()
( R4 g1 x3 i( J' `' ~    .HasForeignKey(c => c.ParentContentId);! v4 M) ]1 f8 W4 \- J
WithMany()没有参数表示第二个端点不是模型类中的属性,尤其是 不是 ChildContent。
4 Z- ?5 b7 y4 a0 t现在,问题仍然存在:ChildContent属于哪种关系?是一对多关系还是多对多关系?; o2 Q# e! T- T
* 选项2a' H5 W6 i4 C+ d1 n: u' [
如果aContent引用其他ChildContents并且不能有第二个Content引用相同的ChildContents(a的子代Content是/ A( ~1 _. c. R0 W" S
唯一的 ,可以这么说),那么您就有一对多的关系。(这类似于订单和订单商品之间的关系:一个订单商品只能属于一个特定的订单。)
6 J$ \: I1 u5 U$ }' i的映射ChildContent如下所示:# h4 O7 I! z! m. S
            modelBuilder.Entity()' w3 w' `6 x( `2 r9 ^6 {8 ~2 }5 V
        .HasMany(c => c.ChildContent)
" I( d) |1 z+ w% Y) R        .WithOptional(); // or WithRequired()- b( x" z- [% y9 h; T
您Content的数据库表中将具有一个附加的外键列,该列属于该关联,但在实体类中没有对应的FK属性。: v3 ?, J, ^  G) |
* 选项2b
( H2 ^, S- t$ L8 X) B如果许多Content可以引用相同ChildContent的,则您具有多对多关系。(这类似于用户和角色之间的关系:同一角色中可以有许多用户,并且一个用户可以有许多角色。)* |' l2 i9 v: D
的映射ChildContent如下所示:
* k6 N7 M4 o$ R" y0 p; {, Z            modelBuilder.Entity()
2 C0 `3 l- B  V" R0 h4 r  L        .HasMany(c => c.ChildContent)
1 X/ ~( }! h# J4 l! Z! ~! @        .WithMany()8 Q" `# @  [$ w. B2 t
        .Map(x =>9 T+ w' |( p6 g
        {+ M+ X( o" a  R/ g8 m) X/ E# U
            x.MapLeftKey(&quotarentId");
$ W/ n  b! P+ N" b( P            x.MapRightKey("ChildId");6 a+ E* G6 G; e7 x+ G: }% H. r
            x.ToTable("ChildContentRelationships");
" Z* r& F( K3 a- I* j: B        });
( T* C# }' d3 A! H( _该映射将ChildContentRelationships在数据库中创建一个联接表,但此表不需要相应的实体。) J0 D, B8 p$ f4 z  N  ^
* 选项2c
5 I0 e" c2 `0 A" H9 K# k( d仅在多对多关系除了两个键(ParentId和ChildId)之外具有更多属性的情况下(例如,诸如CreationDateorRelationshipType或…),您才需要ChildContentRelationship在模型中引入一个新实体:
3 E  k  C* C1 c; I" t            public class ChildContentRelationship
  c/ q/ I7 g3 ?    {0 k; j1 @+ Q0 F( [
        [Key, Column(Order = 0)]
1 J' r* k% |8 q! n/ D3 e& ?/ o        public int ParentId { get; set; }' E! [& U! t* V, g0 Q6 |2 E, m$ _
        [Key, Column(Order = 1)]
/ E" a" _& X+ P! o        public int ChildId { get; set; }% N' n5 k" h9 Z- _/ y$ j) `/ H
        public Content Parent { get; set; }
& b& j/ X- T  V        public Content Child { get; set; }
$ P' k0 C+ R, [        public DateTime CreationDate { get; set; }
: q1 g% N1 D0 F& P6 h% Z3 y        public string RelationshipType { get; set; }
/ U7 O& Q# A  v! Y    }/ {" R- I' V, t& U
现在您的Content班级将有ChildContentRelationships的集合:
8 ?3 a; d, g% [3 _8 L2 y2 M            public virtual ICollection ChildContent
6 W& F) J: h* O% X        { get; set; }
$ N# H' W4 W. P. f& j您有 两个 一对多的关系:# o; E6 {' s. `& v% ~! s; c8 r
            modelBuilder.Entity()3 Y8 e* G; x: X2 h4 w) H
        .HasRequired(ccr => ccr.Parent)
# f2 j# K, T: q9 W$ o9 N1 u! V        .WithMany(c => c.ChildContent)& l/ [2 Q6 D0 q1 r! ^; f- T6 F
        .HasForeignKey(ccr => ccr.ParentId);" S' o; K+ N+ H; R6 g
    modelBuilder.Entity()
' P* g' r* _6 I; n        .HasRequired(ccr => ccr.Child)
" V* X, b. W- f3 t) t9 v        .WithMany()
7 f! K7 [* o3 D2 y( ~; b' O" V% a        .HasForeignKey(ccr => ccr.ChildId);' K' ^- J0 }9 @+ P
我相信您想要选项2a或2b,但是我不确定。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则