首页 > 解决方案 > 在 ASP.Net Core 3.0 中使用表单添加到模型的 IList

问题描述

在尝试学习 ASP.Net Core 的过程中,我决定做一个论坛是一个很好的学习项目。

本着这种精神,我创建了这些模型:

public class Topic
{
    public int Id {get; set;}
    public int PostCount {get; set;}
    public string Title {get; set;}
    public string OriginalPoster {get; set;}
    public IList<Post> Posts{get; set;}
}

public class Post
{
    public int Id {get; set;}
    public DateTime TimeStamp {get; set;}
    public string Poster {get; set;}
    public string Body {get; set;}
}

现在,很明显,当一个人创建一个论坛主题时,一个人也应该创建他们的第一个帖子,以免你留下一个无头的标题。

因此,我创建这个表单的印象是它会让我获得第一个帖子(一旦它起作用,我可以很容易地处理 Post 模型的其他部分):

<form asp-action="Create" asp-controller="Topic" method = "post">
<div class="form-group"><label asp-for="Title"></label>
<input asp-for="Title"></div>

@Html.TextAreaFor(e => e.Posts[0].Body, 10, 55, null) <br />


<button type="submit" class="btn btn-default">Submit</button>

Create但是,当我在我的方法中放置一个断点时,TopicController它向我显示这不起作用(我怀疑这是由于我从未创建过新的 Post 实例)。我得到:

Microsoft.EntityFrameworkCore.DbUpdateConcurrency 异常

说预计会影响 1 行,但是我的数据库上下文的SaveChanges方法会影响 0 行。有什么方法可以创建一个新的 Post 实例并将其添加到我IList<Post>的表单中?

我的控制器的Create功能如下:

    [HttpPost]
    public IActionResult Create(Topic tops)
    {
        if (tops is null)
        {
            throw new System.ArgumentNullException(nameof(tops));
        }

        tops.Posts[0].TimeStamp = DateTime.Now;
        db.Topics.Add(tops);
        db.SaveChanges();  // <-- Error happens here

        return View("Topics", db.Topics.ToList());
    }

任何和所有的帮助将不胜感激。

Topics 的 MySQL 表如下:

+----------------+-------------+------+-----+---------+-------+
| Field          | Type        | Null | Key | Default | Extra |
+----------------+-------------+------+-----+---------+-------+
| Id             | varchar(20) | YES  |     | NULL    |       |
| PostCount      | int(11)     | YES  |     | NULL    |       |
| Title          | varchar(20) | YES  |     | NULL    |       |
| OriginalPoster | varchar(20) | YES  |     | NULL    |       |
+----------------+-------------+------+-----+---------+-------+

对于邮政:

+-----------+-------------+------+-----+---------+----------------+
| Field     | Type        | Null | Key | Default | Extra          |
+-----------+-------------+------+-----+---------+----------------+
| Id        | int(11)     | NO   | PRI | NULL    | auto_increment |
| TimeStamp | datetime(6) | NO   |     | NULL    |                |
| Poster    | longtext    | YES  |     | NULL    |                |
| Body      | longtext    | YES  |     | NULL    |                |
+-----------+-------------+------+-----+---------+----------------+

标签: c#asp.net.netasp.net-mvcasp.net-core

解决方案


原因

  1. 我认为您实际上并没有写入数据库,您的主题模型中的 IList < post > 字段实际上并不存在于数据库中,因此您无法插入它。

解决方案

  1. 数据库设计存在问题。这是一个典型的一对多数据集问题。您需要将这两个表与外键相关联,以便您可以根据键值更新您的 post 表。
  2. 您的数据库表应修改为如下所示
    public class Topic
    {
        [ScaffoldColumn(false)]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int TopicId { get; set; }
        public int PostCount { get; set; }
        public string Title { get; set; }
        public string OriginalPoster { get; set; }
    }

    public class Post
    {
        [ScaffoldColumn(false)]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int PostId { get; set; }
        public int TopicId { get; set; }
        [ForeignKey("TopicId")]
        public DateTime TimeStamp { get; set; }
        public string Poster { get; set; }
        public string Body { get; set; }
    }
  1. 我复制了您的代码并将其放在 GitHub 上。您可以单击此链接查看我如何实现插入操作。这是插入部分的代码
        [HttpPost]
        public async Task<IActionResult> CreateTopic(TopicViewModel model)
        {
            var topic = new Topic
            {
                Title = model.Title,
                OriginalPoster = model.OriginalPoster,
                PostCount = model.PostCount
            };
            await _context.AddAsync(topic);
            await _context.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }
        [HttpPost]
        public async Task<IActionResult> CreatePost(PostViewModel model)
        {
            var post = new Post
            {
                TopicId = model.TopicId,
                TimeStamp = model.TimeStamp,
                Poster = model.Poster,
                Body = model.Body
            };
            await _context.AddAsync(post);
            await _context.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }
  1. 通过上面的描述和代码应该可以解决你当前的问题。

其他提示

  1. 您对 .Net 核心中的模型的理解存在一些偏差。模型可以分为两种:映射数据库实体和为前端页面工作提供服务。相关文件
  2. 的文档。net core 不是很全面。很多小知识都可以在这里找到。

推荐阅读