仅插入相同类型的两个属性之一时 EF 失败

问题描述 投票:0回答:1

我有这个闭包表,应该可以更轻松地获取评论的所有回复、他们的回复、对评论的所有回复(甚至是远方继承人),但是当我尝试插入父项时 - 它会将子项插入为父项。我不记得我是否遇到过这样的问题。

public class ReplyClosure
 {
     [Key]
     public int Id { get; set; }

     public int ParentId { get; set; }

     [ForeignKey(nameof(ParentId))]

     public PostReply Parent { get; set; } = null!;

     public int ChildId { get; set; }
     [ForeignKey(nameof(ChildId))]
     public PostReply Child { get; set; } = null!;

     public int Depth { get; set; } 
     
 }

public class PostReply
{
    [Key]
    public int Id { get; set; }

    public string ForumUserId { get; set; } = string.Empty;

    [ForeignKey(nameof(ForumUserId))]
    public ForumUser ForumUser { get; set; } = null!;

    public int PostId { get; set; }
    [ForeignKey(nameof(PostId))]

    public Post Post { get; set; } = null!;

    [Column(TypeName = "Text")]
    public string Content { get; set; } = String.Empty;


    public DateTime CreatedOn { get; set; } 

    public DateTime ModifiedOn { get; set; }

    public bool IsDeleted { get; set; }

    [InverseProperty(nameof(ReplyClosure.Parent))]
    public virtual List<ReplyClosure> Parents { get; set; } = new List<ReplyClosure>();


    [InverseProperty(nameof(ReplyClosure.Child))]
    public virtual List<ReplyClosure> Children { get; set; } = new List<ReplyClosure>();

}

有问题的代码是这样的: 我尝试用太多的方式来写这个,但没有一个起作用,出于某种原因,我插入了孩子 代替父母。我不知道为什么会这样。当尝试在回复关闭的同时创建回复时,它可能与此有关。我尝试使用另一种方式 - 插入回复并使用导航属性添加父级。也没有用。

PostReply postReply = new PostReply
 {
     CreatedOn = DateTime.Now,
     PostId = replyViewModel.PostId,
     UserId = GetUserId(),
     Content = replyViewModel.Content,
     IsDeleted = false
 };
 var closure = new ReplyClosure
 {
     ParentId = replyViewModel.ParentId, // this is the correct id, confirmed
     Depth = replyViewModel.Depth,
     Child = postReply
 };
          
 await _context.RepliesClosures.AddAsync(closure);
 await _context.SaveChangesAsync();

上下文包含以下数据库关系描述:

builder.Entity<PostReply>()
.HasOne(entry => entry.Post)
.WithMany(entry => entry.PostsReplies)
.OnDelete(DeleteBehavior.Restrict);
  
builder.Entity<ReplyClosure>()
.HasOne(entry => entry.Parent)
.WithMany(entry => entry.Children)
.HasForeignKey(entry => entry.ParentId)
.OnDelete(DeleteBehavior.Restrict);
 
builder.Entity<ReplyClosure>()
.HasOne(entry => entry.Child)
.WithMany(entry => entry.Parents)
.HasForeignKey(entry => entry.ChildId)
.OnDelete(DeleteBehavior.Restrict);

诗。我知道可能有更好的方法在模拟论坛应用程序中设计评论区域,但这是我能想到的最低限度。我知道我可能忘记了一些东西,只是不确定它是什么。谢谢

我尝试使用反向导航属性 - 无济于事,我无法使用原始 sql 事务,我还尝试了聊天 gpt,我所有的数据库关系似乎都是正确的。我想同时创建两个实体并仅使用 saveChanges 一次。我尝试先插入回复,保存,然后插入关闭。它仍然在两个位置插入子项 -parentId 和 childId,所以这一定是我在 dbcontext 或其他东西中定义关系的方式。

asp.net asp.net-mvc database entity-framework many-to-one
1个回答
0
投票

这个配置:

[InverseProperty(nameof(ReplyClosure.Parent))]
public virtual List<ReplyClosure> Parents { get; set; } = new List<ReplyClosure>();

与此配置不匹配:

builder.Entity<ReplyClosure>()
    .HasOne(entry => entry.Parent)
    .WithMany(entry => entry.Children)
    .HasForeignKey(entry => entry.ParentId)
    .OnDelete(DeleteBehavior.Restrict);

第二个流畅的配置看起来是正确的,使用属性应该是:

[InverseProperty(nameof(ReplyClosure.Child))]
public virtual List<ReplyClosure> Parents { get; set; } = new List<ReplyClosure>();

[InverseProperty(nameof(ReplyClosure.Parent))]
public virtual List<ReplyClosure> Children { get; set; } = new List<ReplyClosure>();

如果您看到错误的 FK 更新,我认为 EF 正在使用属性并忽略正确的流畅配置。我建议使用其中之一来避免这种可能的混淆。

© www.soinside.com 2019 - 2024. All rights reserved.