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

如何在ASP.NET MVC中实现DataTable数据新增并关联数据库

问题描述

我是ASP.NET MVC初学者,目前仅掌握在前端DataTable中动态添加行的操作,希望将该DataTable与数据库进行关联,但不知如何实现。我已创建好控制器、模型及数据类,完成了Delete、Edit、Index方法,仅需完善Create方法即可完成整个项目。


前端代码

var table = null;
var arrData = [];
var arrDataPG = [];
arrData.push({
    STT: 1,
    id: 1,
    product_type: "",
    condition1: "",
});
$(document).ready(function () {
    InitTable();
});

function InitTable() {
    if (table !== null && table !== undefined) {
        table.destroy();
    }
    table = $('#tableh').DataTable({
        data: arrData,
        "columns": [
            { "width": "25px" },
            { "width": "300px" },
            { "width": "300px" },
            { "width": "25px" },
        ],
        columnDefs: [
            {
                title: "STT",
                targets: 0,
                data: null,
                render: function (data, type, row, meta) {
                    return (meta.row + meta.settings._iDisplayStart + 1);
                },
            },
            {
                title: "Loại sản phẩm*",
                targets: 1,
                data: null,
                render: function (data, type, row, meta) {
                    return '<textarea style="width: 300px;" id="product_type' + data.id + '" type="text" onchange="ChangeProductType(\'' + data.id + '\',this)" name="' + data.id + '" value="' + data.product_type + '">' + data.product_type + '</textarea>';
                }
            },
            {
                title: "Điều kiện*",
                targets: 2,
                data: null,
                render: function (data, type, row, meta) {
                    return '<textarea style="width: 300px;" id="condition1' + data.id + '" type="text" onchange="ChangeCondition1(\'' + data.id + '\',this)" name="' + data.id + '" value="' + data.condition1 + '">' + data.condition1 + '</textarea>';
                }
            },
            {
                title: "",
                targets: 3,
                data: null,
                className: "dt-center",
                width: "70",
                render: function (data, type, row, meta) {
                    return '<div class="btn btn-danger removePG" style="cursor: pointer;font-size:25px;" ><i class="fa-solid fa-trash"></i></div>';
                }
            },
        ],
    });
    table.columns.adjust().draw();
}

$('#addRow').on('click', function () {
    console.log(arrData.length);
    var ida = arrData.length > 0 ? arrData[0].id : 1;

    for (var i = 0; i < arrData.length; i++) {
        if (arrData[i].id > ida) {
            ida = arrData[i].id;
        }
    };
    arrData.push({
        STT: ida + 1,
        id: ida + 1,
        product_type: "",
        condition1: "",
    });
    if (table != null) {
        table.clear();
        table.rows.add(arrData).draw();
    }
});
$('#tableh').on('click', '.removePG', function () {
    var tableq = $('#tableh').DataTable();
    var rowData = tableq.row($(this).parents('tr')).data();
    removePG(rowData.id);
    tableq.row($(this).parents('tr')).remove().draw();
});

function removePG(idc) {
    let id = parseInt(idc);
    if (arrData !== undefined) {
        arrData = arrData.filter(item => item.id !== id);
    }
}

// 同步输入框内容到数组
function ChangeProductType(id, element) {
    var item = arrData.find(x => x.id == parseInt(id));
    if(item) {
        item.product_type = element.value;
    }
}

function ChangeCondition1(id, element) {
    var item = arrData.find(x => x.id == parseInt(id));
    if(item) {
        item.condition1 = element.value;
    }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet"type="text/css"href="https://cdn.datatables.net/1.12.1/css/jquery.dataTables.min.css">

<table id="tableh" class="cell-border hover" style="width:100%"></table>
        
<button style="width: 86px;" id="addRow" class="btn btn-success add">Addrow<i class="fa fa-plus" aria-hidden="true"></i></button>
<!-- 新增提交按钮 -->
<button style="width: 100px;" id="submitBtn" class="btn btn-primary">提交数据</button>

<script src="https://code.jquery.com/jquery-3.5.1.js"></script>
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.12.1/js/jquery.dataTables.js"></script>
<script src="https://kit.fontawesome.com/60bf89e922.js" crossorigin="anonymous"></script>
<!-- 添加防伪造令牌 -->
@Html.AntiForgeryToken()

<!-- 批量提交AJAX逻辑 -->
<script>
$('#submitBtn').on('click', function() {
    // 过滤掉未填写产品类型的无效行
    var submitData = arrData.filter(item => item.product_type.trim() !== '');
    
    if(submitData.length === 0) {
        alert('至少要填写一行有效数据');
        return;
    }

    $.ajax({
        url: '/Firstrow/CreateMultiple',
        type: 'POST',
        contentType: 'application/json',
        data: JSON.stringify(submitData),
        headers: {
            'RequestVerificationToken': $('input[name="__RequestVerificationToken"]').val()
        },
        success: function(response) {
            if(response.success) {
                alert('提交成功');
                window.location.href = '/Firstrow/Index';
            } else {
                alert('提交失败:' + response.message);
            }
        },
        error: function() {
            alert('服务器错误');
        }
    });
});
</script>

控制器代码

using Microsoft.AspNetCore.Mvc;
using WebApplication1.Data;
using WebApplication1.Models;

namespace WebApplication1.Controllers
{
public class FirstrowController : Controller
{
    private readonly ApplicationDbContext _db;

    public FirstrowController(ApplicationDbContext db)
    {
        _db = db; 
    }

    public IActionResult Index()
    {
        IEnumerable<Firstrow> objFirstrowList = _db.Firstrow;
        return View(objFirstrowList);
    }

    //Get
    public IActionResult Create()
    {
        return View();
    }

    //POST 单行创建(保留原方法,按需使用)
    [HttpPost]
    [ValidateAntiForgeryToken]
    public IActionResult Create(Firstrow obj)
    {
        if (obj.product_type == obj.condition1.ToString())
        {
            ModelState.AddModelError("name", "Nhập thiếu kìa fen");
        }
        if (ModelState.IsValid) 
        {
            _db.Firstrow.Add(obj);
            _db.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(obj);
    }

    //POST 批量创建新方法
    [HttpPost]
    [ValidateAntiForgeryToken]
    public IActionResult CreateMultiple([FromBody] List<Firstrow> rows)
    {
        if(rows == null || rows.Count == 0)
        {
            return Json(new { success = false, message = "没有提交任何数据" });
        }

        foreach(var row in rows)
        {
            if(string.IsNullOrWhiteSpace(row.product_type))
            {
                ModelState.AddModelError("", $"第{row.id}行的产品类型不能为空");
            }
        }

        if(ModelState.IsValid)
        {
            _db.Firstrow.AddRange(rows);
            _db.SaveChanges();
            return Json(new { success = true });
        }

        // 收集所有错误信息返回前端
        var errors = ModelState.Values.SelectMany(v => v.Errors).Select(e => e.ErrorMessage);
        return Json(new { success = false, message = string.Join("; ", errors) });
    }

    //Get
    public IActionResult Edit(int? id)
    {
        if (id == null || id == 0)
        {
            return NotFound();
        }
        var FirstrowFromDb = _db.Firstrow.Find(id);

        if (FirstrowFromDb == null)
        {
            return NotFound();
        }

        return View(FirstrowFromDb);
    }

    //POST
    [HttpPost]
    [ValidateAntiForgeryToken]
    public IActionResult Edit(Firstrow obj)
    {
        if (obj.product_type == obj.condition1.ToString())
        {
            ModelState.AddModelError("name", "Nhập thiếu kìa fen");
        }
        if (ModelState.IsValid)
        {
            _db.Firstrow.Update(obj);
            _db.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(obj);
    }

    //Get
    public IActionResult Delete(int? id)
    {
        if (id == null || id == 0)
        {
            return NotFound();
        }
        var FirstrowFromDb = _db.Firstrow.Find(id);

        if (FirstrowFromDb == null)
        {
            return NotFound();
        }

        return View(FirstrowFromDb);
    }

    //POST
    [HttpPost,ActionName("Delete")]
    [ValidateAntiForgeryToken]
    public IActionResult DeletePOST(int? id)
    {
        var obj = _db.Firstrow.Find(id);
        if (obj == null) 
        {
            return NotFound();
        }
        _db.Firstrow.Remove(obj);
            _db.SaveChanges();
            return RedirectToAction("Index");
    }
}
}

模型代码

using System.ComponentModel.DataAnnotations;

namespace WebApplication1.Models
{
public class Firstrow
{
    [Key]
    public int id { get; set; }
    [Required]
    public string product_type { get; set; }
    public string condition1 { get; set; }
   }
}

实现说明

  1. 前端调整:

    • 补充输入框内容同步方法,确保用户输入实时更新到arrData数组
    • 修复删除行逻辑,保证数组与DataTable数据完全同步
    • 新增批量提交按钮和AJAX逻辑,过滤无效数据后发送到后端
    • 添加防伪造令牌,符合ASP.NET MVC的安全验证要求
  2. 后端调整:

    • 新增CreateMultiple方法,接收前端传来的多行数据列表
    • 对批量数据进行必填字段验证,返回明确的错误提示
    • 使用AddRange批量插入数据,提升数据库操作效率
    • 返回JSON格式结果,方便前端处理提交状态
  3. 注意事项:

    • 模型的id为自增主键,EF Core会自动生成新ID,前端的id仅用于行标识,不影响数据库存储
    • 确保ApplicationDbContext已正确配置数据库连接字符串
    • 可根据业务需求调整验证规则和提示文案

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 07:25:20