You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core中批量生成Article后无法保存至数据库求助

问题:生成的Article记录无法保存到数据库

我拥有Stock和Article两个模型,Article中以StockId作为外键。希望根据Stock的Quantite值生成对应数量的Article记录并添加到数据库中,已经解决了表格仅显示表头的问题,但现在填写的Article数据无法保存到数据库。

现有代码

StockController

public IActionResult AddArticle(int id)
{
    Stock stock = _dbcontext.Stock.Where(e => e.StockId == id).FirstOrDefault();
    
    for(int i=1; i<= stock.Quantite;i++)
    {
        stock.Articles.Add(new Article() { ArticleId = i });
    }
    return PartialView("_AddArticlePartialView", stock);
}

[HttpPost]
public IActionResult AddArticle(List<Article> article)
{
    if (article != null)
    {
        _dbcontext.Article.AddRange(article);
        _dbcontext.SaveChanges();
        return RedirectToAction("Index");
    }
    return View();
}

Index.cshtml

@model IEnumerable<Stock>

@{
    ViewData["Title"] = "Stock";
    Layout = "~/Views/Shared/_Theme.cshtml";
 }
<table class="table table-bordered table-hover" id="display">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.CategoryId)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Designation)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Quantite)
            </th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        @foreach (var item in Model)
        {
            <tr>
                <td>
                    @Html.DisplayFor(modelItem => item.Category.CategoryName)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Designation)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Quantite)
                </td>

                <td>
                    <div class="btn-group-sm">
                        <button class="btn btn-primary" data-toggle="modal" data-target="@("#AddArticle-"+item.StockId)" data-url="@Url.Action($"AddArticle/{item.StockId}")"><i class="fa fa-plus"></i>Ajouter Articles</button>
                        @await Html.PartialAsync("_AddArticlePartialView", item)
                    </div>
                </td>
            </tr>
        }
    </tbody>
</table>

_AddArticlePartialView.cshtml

@model StockProject.Models.Stock

@{
    ViewData["Title"] = "_AddArticlePartialView";

}

<div class="modal fade" role="dialog" tabindex="-1" id="@("#AddArticle-"+Model.StockId)" aria-labelledby="addArticleLabel" aria-hidden="true" >
    <div class="modal-dialog modal-xl modal-dialog-scrollable" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h3 class="modal-title">Articles</h3>
            </div>
            <div class="modal-body">
                <form asp-action="AddArticle" method="post">
                    <div class="card">
                        <div class="card-header">
                            <h3 class="card-title">Articles</h3>

                        </div>
                        
                        <div class="card-body">
                            <table class="table table-bordered" id="articleTable">
                                <thead>
                                    <tr>
                                        <th>Numero de Serie</th>
                                        <th>Marque</th>
                                        <th>Etat</th>                                        
                                    </tr>
                                </thead>
                                <tbody>
                                    @for (int i = 0; i < Model.Articles.Count; i++)
                                    {
                                        <tr>
                                            <td>
                                                @Html.EditorFor(x => x.Articles[i].NumeroSerie, new { htmlAttributes = new { @class = "form-control" } })
                                            </td>

                                            <td>
                                                @Html.EditorFor(x => x.Articles[i].Marque, new { htmlAttributes = new { @class = "form-control" } })
                                            </td>
                                            <td>
                                                @Html.DropDownListFor(x => x.Articles[i].Etat, new List<SelectListItem> {
                                                       new SelectListItem { Value = "En Marche" , Text = "En Marche" },
                                                       new SelectListItem { Value = "En Panne" , Text = "En Panne" },

                                                    },
                                                  new { @class = "form-control" })
                                            </td>
                                            
                                        </tr>
                                    }

                                </tbody>
                            </table>
                        </div>
                    </div>
                    <div class="modal-footer">
                        <button type="button" class="btn btn-secondary" data-dismiss="modal">Annuler</button>
                        <button type="submit" class="btn btn-primary">Sauvegarder</button>
                    </div>
                </form>
            </div>
        </div>
    </div>
</div>

问题原因分析

  1. 模型绑定不匹配:
    视图基于Stock模型渲染,表单字段命名格式为Articles[0].NumeroSerie,但HttpPost方法接收的是List<Article>,ASP.NET Core无法将表单数据正确绑定到该参数,导致article参数为null或空集合。

  2. 缺少StockId关联:
    生成的Article对象未设置对应的StockId,即使保存成功,也无法关联到目标Stock记录。

  3. ArticleId手动赋值问题:
    如果ArticleId是数据库自增主键,手动设置ArticleId = i会导致主键冲突,EF无法正常保存。

解决方案

1. 修改HttpPost方法参数与逻辑

将参数改为Stock stock,并为每个Article设置StockId:

[HttpPost]
public IActionResult AddArticle(Stock stock)
{
    if (stock?.Articles != null && stock.Articles.Any())
    {
        foreach (var article in stock.Articles)
        {
            // 关联当前Stock的Id
            article.StockId = stock.StockId;
            _dbcontext.Article.Add(article);
        }
        _dbcontext.SaveChanges();
        return RedirectToAction("Index");
    }
    return View();
}

2. 修正Get方法中Article的生成逻辑

移除手动设置ArticleId的代码,避免主键冲突,同时清空临时Articles防止重复添加:

public IActionResult AddArticle(int id)
{
    Stock stock = _dbcontext.Stock.Where(e => e.StockId == id).FirstOrDefault();
    
    // 清空临时添加的Articles,避免重复打开modal时累积
    stock.Articles.Clear();
    for(int i=1; i<= stock.Quantite;i++)
    {
        // 不设置ArticleId,由数据库自增生成
        stock.Articles.Add(new Article());
    }
    return PartialView("_AddArticlePartialView", stock);
}

3. 在表单中添加StockId隐藏字段

在_AddArticlePartialView.cshtml的<form>标签内添加隐藏字段,确保StockId能被正确提交:

<form asp-action="AddArticle" method="post">
    <!-- 添加这行代码 -->
    @Html.HiddenFor(x => x.StockId)
    
    <!-- 原有表单内容 -->
    <div class="card">
        ...
    </div>
</form>

4. 确认模型配置正确性

确保Article和Stock模型的导航属性与外键配置正确:

// Article模型
public class Article
{
    public int ArticleId { get; set; } // 自增主键
    public string NumeroSerie { get; set; }
    public string Marque { get; set; }
    public string Etat { get; set; }
    
    public int StockId { get; set; } // 外键
    public Stock Stock { get; set; } // 导航属性
}

// Stock模型
public class Stock
{
    public int StockId { get; set; }
    public int CategoryId { get; set; }
    public string Designation { get; set; }
    public int Quantite { get; set; }
    
    public Category Category { get; set; }
    public ICollection<Article> Articles { get; set; } = new List<Article>();
}

内容的提问来源于stack exchange,提问作者user3309231

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 04:44:59