C# EF Core SqlException:无法在表';MenuCategories';当IDENTITY_INSERT设置为OFF时

C# EF Core SqlException:无法在表';MenuCategories';当IDENTITY_INSERT设置为OFF时,c#,sql,entity-framework,asp.net-core,C#,Sql,Entity Framework,Asp.net Core,我正试图将一些数据保存到MenuItems表中,但错误阻止了我 SqlException:当identity_insert设置为OFF时,无法在表“MenuCategories”中为identity列插入显式值 我只是尝试使用我拥有的类别id设置外键,我不太清楚为什么会出现上述错误 这是我的MenuItem型号: public class MenuItemViewModel { [Key] [Column("MenuItem_Id")] public int MenuIt

我正试图将一些数据保存到MenuItems表中,但错误阻止了我

SqlException:当identity_insert设置为OFF时,无法在表“MenuCategories”中为identity列插入显式值

我只是尝试使用我拥有的类别id设置外键,我不太清楚为什么会出现上述错误

这是我的
MenuItem
型号:

public class MenuItemViewModel
{
    [Key]
    [Column("MenuItem_Id")]
    public int MenuItemId { get; set; }

    [Required]
    public string Name { get; set; }

    [Required]
    public string Description { get; set; }

    [Required]
    public decimal Price { get; set; }

    [Required]
    [Column("MenuCategory_Id")]
    public MenuCategoryViewModel MenuCategory { get; set; }
}
public class MenuCategoryViewModel
{
    [Key]
    [Column("MenuCategory_Id")]
    public int MenuCategoryId { get; set; }

    [Required]
    public string Name { get; set; }
}
这是我的
菜单分类
型号:

public class MenuItemViewModel
{
    [Key]
    [Column("MenuItem_Id")]
    public int MenuItemId { get; set; }

    [Required]
    public string Name { get; set; }

    [Required]
    public string Description { get; set; }

    [Required]
    public decimal Price { get; set; }

    [Required]
    [Column("MenuCategory_Id")]
    public MenuCategoryViewModel MenuCategory { get; set; }
}
public class MenuCategoryViewModel
{
    [Key]
    [Column("MenuCategory_Id")]
    public int MenuCategoryId { get; set; }

    [Required]
    public string Name { get; set; }
}

我正在尝试为它分配现有类别的id,我不希望它创建新类别。

根据您的评论,您希望使用现有id不添加新类别,那么您的保存操作有点错误。
\u Context.add(menuItem)
将导致数据库
INSERT
启动-这是因为
.Add()
将所有实体标记为要保存到上下文中的新实体,但是您不希望这样做-您应该做的是添加
菜单项
-查询数据库以获取要附加到它的
菜单项
-然后在
菜单项
上设置它,然后保存。

我必须假设您的
DbContext
类如下:

public class Context: DbContext
{
    public Context(DbContextOptions<MenuContext> options)
        : base(options)
    { }

    public DbSet<MenuCategory> MenuCategories{ get; set; }
    public DbSet<MenuItem> MenuItems { get; set; }
}
公共类上下文:DbContext
{
公共上下文(DbContextOptions选项)
:基本(选项)
{ }
公共数据库集菜单类别{get;set;}
公共数据库集菜单项{get;set;}
}
因此,可以通过以下方式对控制器进行编码:

public async Task<IActionResult> Create(MenuItemViewModel model)
{
    if (ModelState.IsValid)
    {
        var menuItem = new MenuItem 
        {
            Name = model.Name,
            ...
        };

        var menuCategory = _Context.MenuCategories.Find(model.MenuCategory.MenuCategoryId);
        menuItem.MenuCategory = menuCategory;
        _Context.MenuItems.Add(menuItem);
        await _Context.SaveChangesAsync();
        return RedirectToAction(nameof(Index), new { id = menuItem.MenuCategory.MenuCategoryId });
    }
    return View(menuItem);
}
公共异步任务创建(MenuItemViewModel)
{
if(ModelState.IsValid)
{
var menuItem=新的menuItem
{
Name=model.Name,
...
};
var menuCategory=_Context.MenuCategories.Find(model.menuCategory.MenuCategoryId);
menuItem.MenuCategory=MenuCategory;
_Context.MenuItems.Add(menuItem);
wait_Context.SaveChangesAsync();
返回RedirectToAction(nameof(Index),new{id=menuItem.MenuCategory.MenuCategoryId});
}
返回视图(菜单项);
}
据我所知,您假设如果您告诉您的视图您的
MenuCategory
具有选定的id,您的视图将填充
MenuCategory
。它不是那样工作的。视图无法知道您的
菜单类别是什么。您需要使用发生在控制器中的
DbContext
填充这些值


此外,最好将实体与视图模型分开。如果您的类有自己的简单职责,那么就容易多了:您的实体将表示数据库中的逻辑记录,您的视图模型将表示来自控制器和流向控制器的数据。

如果您“隐式”将实体添加到数据库中,也会出现此错误,已保存,然后尝试手动添加

很明显,下面的代码很糟糕,写这篇文章毫无意义。但是,在更复杂的情况下,可能会意外地这样做

var category = new MenuCategoryViewModel() { ... };

// assign category to menu item    
var model = new MenuItemViewModel() 
            {
                MenuCategory = category 
            };  

db.Add(model);
db.SaveChanges();

// 'category' object has an ID because we saved it
// even though it was never explicitly added to the context

// add the category to the context 
db.Add(category);
db.SaveChanges();  // fails with IDENTITY error

如果您在添加实体时未将其显式添加到上下文中,则在已为其分配密钥之后,不得再添加该实体。

提示:上述错误表示您要插入的Id是标识列,这意味着您必须让数据库服务器控制它如何填充
MenuItemId
,除非您将
Identity\u Insert
设置为off。我不是实体框架核心方面的专家,但您是否尝试在未填充
MenuItemId
的情况下传递对象?你为什么需要自己填充
MenuItemId
呢?@KristianneNerona我正在尝试自己填充它,因为我想使用一个现有类别,我不想让它创建一个新类别。你能确认MenuCategoryId是否定义为数据库中的标识列吗?哦,好的,这解决了我的问题。因此,每当我需要使用外键的现有id时,我必须首先从数据库中获取它的对象,然后分配它,然后保存它?通常是的,这是因为您希望生成的SQL语句是一个更新,它将通过对现有实体的“更改跟踪”触发