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

Visual Studio添加迁移与控制器后数据库MenuItem表未生成如何解决

问题描述

我正在Visual Studio Community中开发应用,希望将已创建的Model同步生成为数据库中的表,目前遇到问题但经验不足无法定位原因,已花费数小时搜索相关关键词,未找到有效解决信息。

具体问题

我目前创建了Alert和MenuItem两个Model,为Alert模型搭建了脚手架控制器后,已成功同步到数据库中,运行完全符合预期。但后续处理数据库时未能得到相同结果:我创建了MenuItem模型,为其新增脚手架项,执行Add-Migration命令,再运行Update-Database命令,刷新SQL Server Object Explorer后,数据库中仅存在Alert表。
以下是可能有参考价值的相关文件,我无法理解为何数据库没有按照所学逻辑新增对应表。

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;

namespace _6thStreetDive.Models
{
    public class MenuItem
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Desc { get; set; }
        public bool ShowMainPrice { get; set; }

        [Column(TypeName = "decimal(18,4)")]
        public decimal MainPrice { get; set; }
        public string Category { get; set; }

        [NotMapped]
        public Dictionary<string, decimal> Options { get; set; }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using _6thStreetDive.Data;
using _6thStreetDive.Models;

namespace _6thStreetDive.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class MenuItemsController : ControllerBase
    {
        private readonly _6thStreetDiveContext _context;

        public MenuItemsController(_6thStreetDiveContext context)
        {
            _context = context;
        }

        // GET: api/MenuItems
        [HttpGet]
        public async Task<ActionResult<IEnumerable<MenuItem>>> GetMenuItem()
        {
            return await _context.MenuItem.ToListAsync();
        }

        // GET: api/MenuItems/5
        [HttpGet("{id}")]
        public async Task<ActionResult<MenuItem>> GetMenuItem(int id)
        {
            var menuItem = await _context.MenuItem.FindAsync(id);

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

            return menuItem;
        }

        // PUT: api/MenuItems/5
        // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
        [HttpPut("{id}")]
        public async Task<IActionResult> PutMenuItem(int id, MenuItem menuItem)
        {
            if (id != menuItem.Id)
            {
                return BadRequest();
            }

            _context.Entry(menuItem).State = EntityState.Modified;

            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!MenuItemExists(id))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }

            return NoContent();
        }

        // POST: api/MenuItems
        // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
        [HttpPost]
        public async Task<ActionResult<MenuItem>> PostMenuItem(MenuItem menuItem)
        {
            _context.MenuItem.Add(menuItem);
            await _context.SaveChangesAsync();

            return CreatedAtAction("GetMenuItem", new { id = menuItem.Id }, menuItem);
        }

        // DELETE: api/MenuItems/5
        [HttpDelete("{id}")]
        public async Task<IActionResult> DeleteMenuItem(int id)
        {
            var menuItem = await _context.MenuItem.FindAsync(id);
            if (menuItem == null)
            {
                return NotFound();
            }

            _context.MenuItem.Remove(menuItem);
            await _context.SaveChangesAsync();

            return NoContent();
        }

        private bool MenuItemExists(int id)
        {
            return _context.MenuItem.Any(e => e.Id == id);
        }
    }
}

Context.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using _6thStreetDive.Models;

namespace _6thStreetDive.Data
{
    public class _6thStreetDiveContext : DbContext
    {
        public _6thStreetDiveContext (DbContextOptions<_6thStreetDiveContext> options)
            : base(options)
        {
        }
        public DbSet<_6thStreetDive.Models.Alert> Alert { get; set; }
        public DbSet<_6thStreetDive.Models.MenuItem> MenuItem { get; set; }

    }
}

已尝试的解决方案

  • 删除迁移记录,重新执行InitialCreate初始化
  • 新增多个迁移记录
  • 删除MenuItem控制器后重新执行脚手架搭建
  • 关闭并重启Visual Studio
  • 重建项目后重复上述步骤

执行操作步骤

  • 创建Model
  • 添加新脚手架项
  • 执行Add-Migration "自定义迁移名称"
  • 执行Update-Database
  • 刷新SSOE视图

解决方案

按以下优先级排查即可定位问题:

  1. 检查迁移文件内容
    执行Add-Migration后,打开项目Migrations文件夹下刚生成的迁移文件,查看Up方法中是否包含创建MenuItem表的代码:
    • 如果没有,执行Remove-Migration删除空迁移,先修复MenuItem模型的可空引用问题:将所有string属性添加默认值或标记为可空,示例:public string Name { get; set; } = string.Empty;,修复后重新执行Add-Migration即可。
    • 如果有,进入下一步排查。
  2. 校验连接字符串一致性
    打开appsettings.json检查默认连接字符串对应的数据库实例、库名,确认与SQL Server Object Explorer中打开的数据库完全一致,90%的同类问题都是连接到了错误的数据库实例导致。
  3. 验证迁移执行状态
    打开目标数据库的__EFMigrationsHistory系统表,查看本次迁移的记录是否已存在:
    • 如果不存在,执行Update-Database -Verbose查看详细执行日志,定位执行失败的具体原因。
    • 如果存在但无对应表,执行Script-Migration生成完整SQL脚本,手动在目标数据库执行即可看到具体报错信息。
  4. 终极解决方法
    如果上述步骤都无效,直接删除本地数据库文件、清空项目Migrations文件夹,重新执行Add-Migration InitialCreate和Update-Database,即可生成包含两个表的全新数据库。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 22:24:03