【问题标题】:Stack overflow when adding an entity with multiple one-to-one relationship with the same table in Entity Framework Core在 Entity Framework Core 中添加与同一个表具有多个一对一关系的实体时堆栈溢出
【发布时间】:2020-03-09 20:58:37
【问题描述】:

在 Entity Framework Core 中添加具有多个一对一关系的实体时遇到问题。根据this 问题,我有以下几点:

public class Article
{
    public int Id { get; set; }
    public int? PreviousId { get; set; }
    public Article Previous { get; set; }
    public int? NextId { get; set; }
    public Article Next { get; set; }
}

DbContextOnModelCreating 中,就像我一样:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    modelBuilder.HasDefaultSchema("ab");
    modelBuilder.ApplyConfiguration(new ArticleEntityTypeConfiguration());
}

public class ArticleEntityTypeConfiguration : IEntityTypeConfiguration<Article>
{
    public void Configure(EntityTypeBuilder<Article> builder)
    {
        builder.ToTable("Articles");

        builder.HasKey(table => table.Id);
        builder.Property(table => table.Id).ValueGeneratedOnAdd();

        builder.HasOne(table => table.Previous).WithOne().HasForeignKey<Article>(table => table.PreviousId);
        builder.HasOne(table => table.Next).WithOne().HasForeignKey<Article>(table => table.NextId);
    }
}

添加新文章时,我收到堆栈溢出错误,应用程序崩溃。我添加一篇文章,代码如下:

public Task AddNewArticleAsync(Article article)
{
    var newArticle = new Article();

    article.Next = newArticle;
    newArticle.Previous = article;

    await _dbContext.Programs.AddAsync(article);
}

你知道我怎样才能避免这个错误吗?谢谢!

【问题讨论】:

标签: c# entity-framework asp.net-core .net-core entity-framework-core


【解决方案1】:

如果您添加新文章,PreviousId/NextId 应该为 null 或现有的Article.Id。如果您的 Artice.Id 增加,previousId 是现有记录的最大 id。

下面是保存新文章的演示:

[HttpPost]
public async Task<IActionResult> Create(Article article)
{
    if (ModelState.IsValid)
    {
        int minArticleId = _context.Articles.Max(a => a.Id);
        var previous = await _context.Articles.Where(s => s.Id == minArticleId).FirstOrDefaultAsync();
        article.PreviousId = minArticleId;
        _context.Add(article);
        await _context.SaveChangesAsync();

        previous.NextId = article.Id;          
        _context.Update(previous);
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }

    return View(article);
}

【讨论】:

  • 其实导航不是这样的。有一些线程,因此 PreviousId 不是数据库中的最小 id 所必需的。这就是为什么上一篇文章,或者至少是上一篇文章id,必须是操作的输入。
【解决方案2】:

因此,我继续对此进行调查,并找到了 this 的答案,它帮助我解决了这个问题。诀窍是将DbContextOnModelCreating 更改为:

public void Configure(EntityTypeBuilder<Article> builder)
{
    builder.ToTable("Articles");

    builder.HasKey(table => table.Id);
    builder.Property(table => table.Id).ValueGeneratedOnAdd();

    builder
        .HasOne(table => table.Previous)
        .WithOne() // <-- one of this must be empty
        .HasForeignKey<Article>(table => table.PreviousId)
        .OnDelete(DeleteBehavior.Restrict);

    builder
        .HasOne(table => table.Next)
        .WithOne(table => table.Previous)
        .HasForeignKey<Article>(table => table.NextId);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-30
    • 1970-01-01
    相关资源
    最近更新 更多