C# EF Core SqlException:无法在表';MenuCategories';当IDENTITY_INSERT设置为OFF时
我正试图将一些数据保存到MenuItems表中,但错误阻止了我 SqlException:当identity_insert设置为OFF时,无法在表“MenuCategories”中为identity列插入显式值 我只是尝试使用我拥有的类别id设置外键,我不太清楚为什么会出现上述错误 这是我的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
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语句是一个更新,它将通过对现有实体的“更改跟踪”触发