我有这个闭包表,应该可以更轻松地获取评论的所有回复、他们的回复、对评论的所有回复(甚至是远方继承人),但是当我尝试插入父项时 - 它会将子项插入为父项。我不记得我是否遇到过这样的问题。
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 或其他东西中定义关系的方式。
这个配置:
[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 正在使用属性并忽略正确的流畅配置。我建议使用其中之一来避免这种可能的混淆。