添加行时获取 DbUpdateException
Getting DbUpdateException when adding a row
我正在尝试在 table 中添加一条记录,但它不起作用。错误消息告诉我无法在 ProductCategories
的标识列中插入显式值,但我不知道我正在这样做。也许关于实体导航我没有得到一些东西,或者我的模型以某种方式没有正确链接?
SqlException: Cannot insert explicit value for identity column in table 'ProductCategories' when IDENTITY_INSERT is set to OFF.
Cannot insert explicit value for identity column in table 'Products' when IDENTITY_INSERT is set to OFF.
System.Data.SqlClient.SqlCommand+<>c.b__108_0(Task result)
DbUpdateException: An error occurred while updating the entries. See the inner exception for details.
Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch+d__32.MoveNext()
这是失败的代码(在 await _context.SaveChangesAsync();
):
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> FrontPageProduct(ViewModelFrontPageProduct frontPageProduct)
{
var fpp = new FrontPageProduct()
{
ProductCategoryId = frontPageProduct.ProductCategoryId,
ProductId = frontPageProduct.ProductId,
SortOrder = 0
};
_context.Add(fpp);
await _context.SaveChangesAsync();
return View("Index", new { id = fpp.ProductCategoryId, tab = 2 });
}
涉及的实体模型如下:
public class Product
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Title { get; set; }
public string Info { get; set; }
public decimal Price { get; set; }
public List<FrontPageProduct> InFrontPages { get; set; }
public List<ProductInCategory> InCategories { get; set; }
}
public class ProductCategory
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public int SortOrder { get; set; }
public string Title { get; set; }
[ForeignKey(nameof(ParentCategory))]
public int? ParentId { get; set; }
public ProductCategory ParentCategory { get; set; }
public ICollection<ProductCategory> Children { get; set; } = new List<ProductCategory>();
public List<ProductInCategory> ProductInCategory { get; set; }
}
public class FrontPageProduct
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public int ProductCategoryId { get; set; }
public int ProductId { get; set; }
public int SortOrder { get; set; }
[ForeignKey("ProductId")]
public virtual Product Product { get; set; }
[ForeignKey("ProductCategoryId")]
public virtual ProductCategory ProductCategory { get; set; }
}
fpp
对象的调试检查显示 ProductCategoryId
和 ProductId
的值是正确的:
哪里 is/are 我的 mistake/s?
EDIT 我将建议的 [Key]
和 [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
添加到所有模型,但我仍然遇到相同的错误。
我认为 Id
字段在 EF 中总是默认设置为主键。
EDIT 2 我尝试在我的控制器方法中添加 [FromBody]
,但这只会导致空白屏幕,没有错误消息,也没有对数据库。
编辑 3 我将 [ForeignKey("ProductId")]
和 [ForeignKey("ProductCategoryId")]
添加到 FrontPageProduct
模型,但仍然得到相同的 SqlException。
EDIT 4 这些是我的四个 table 的外键:
FrontPageProducts
:
FK_FrontPageProducts_ProductCategories_ProductCategoryId
FK_FrontPageProducts_Products_ProductId
ProductCategories
:
FK_ProductCategories_ProductCategories_ParentId
Products
:
none
ProductsInCategories
:
FK_ProductsInCategories_FrontPageProducts_FrontPageProductId
FK_ProductsInCategories_ProductCategories_ProductCategoryId
FK_ProductsInCategories_Products_ProductId
Id 字段应该是数据库中的主键,以便您可以在实体模型中指定它。 - 添加[密钥]
public class Product
{
[Key]
public int Id { get; set; }
public string Title { get; set; }
public string Info { get; set; }
public decimal Price { get; set; }
public IEnumerable<FrontPageProduct> InFrontPages { get; set; }
public List<ProductInCategory> InCategories { get; set; }
}
看起来您不需要为 "int Id" 字段设置 DatabaseGenerated 属性,这是一个约定并假设它是标识列。
顺便说一句,你确定你得到了同样的错误吗? imgur link 对我不起作用。您的 FrontPage 是否真的需要 Product 和 ProductCategory class,如果您可以轻松地将它们注释掉并进行测试,请这样做,如果不能,您可以尝试如下设置它们的值。
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> FrontPageProduct(ViewModelFrontPageProduct frontPageProduct)
{
var fpp = new FrontPageProduct()
{
ProductCategoryId = frontPageProduct.ProductCategoryId,
ProductId = frontPageProduct.ProductId,
Product = _context.Set<Product>().Find(frontPageProduct.ProductId),
ProductCategory = _context.Set<ProductCategory>().Find(frontPageProduct.ProductCategoryId),
SortOrder = 0
};
_context.Add(fpp);
await _context.SaveChangesAsync();
return View("Index", new { id = fpp.ProductCategoryId, tab = 2 });
}
将 Key 和 DatabaseGenerated 属性应用于模型中的每个 Id 列,以便 EF 知道它是一个标识列,并且需要取回生成的 id 值。
public class Product
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Title { get; set; }
public string Info { get; set; }
public decimal Price { get; set; }
[InverseProperty("Product")]
public IEnumerable<FrontPageProduct> InFrontPages { get; set; }
public List<ProductInCategory> InCategories { get; set; }
}
public class ProductCategory
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public int SortOrder { get; set; }
public string Title { get; set; }
[ForeignKey(nameof(ParentCategory))]
public int? ParentId { get; set; }
public ProductCategory ParentCategory { get; set; }
public ICollection<ProductCategory> Children { get; set; } = new List<ProductCategory>();
public List<ProductInCategory> ProductInCategory { get; set; }
}
public class FrontPageProduct
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public int ProductCategoryId { get; set; }
public int ProductId { get; set; }
public int SortOrder { get; set; }
[ForeignKey("ProductId")]
public virtual Product Product { get; set; }
[ForeignKey("ProductCategoryId ")]
public virtual ProductCategory ProductCategory { get; set; }
}
编辑:您应该添加导航属性,就像我在上面添加的那样。使它们虚拟化也有助于延迟加载。
我正在尝试在 table 中添加一条记录,但它不起作用。错误消息告诉我无法在 ProductCategories
的标识列中插入显式值,但我不知道我正在这样做。也许关于实体导航我没有得到一些东西,或者我的模型以某种方式没有正确链接?
SqlException: Cannot insert explicit value for identity column in table 'ProductCategories' when IDENTITY_INSERT is set to OFF. Cannot insert explicit value for identity column in table 'Products' when IDENTITY_INSERT is set to OFF. System.Data.SqlClient.SqlCommand+<>c.b__108_0(Task result)
DbUpdateException: An error occurred while updating the entries. See the inner exception for details. Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch+d__32.MoveNext()
这是失败的代码(在 await _context.SaveChangesAsync();
):
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> FrontPageProduct(ViewModelFrontPageProduct frontPageProduct)
{
var fpp = new FrontPageProduct()
{
ProductCategoryId = frontPageProduct.ProductCategoryId,
ProductId = frontPageProduct.ProductId,
SortOrder = 0
};
_context.Add(fpp);
await _context.SaveChangesAsync();
return View("Index", new { id = fpp.ProductCategoryId, tab = 2 });
}
涉及的实体模型如下:
public class Product
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Title { get; set; }
public string Info { get; set; }
public decimal Price { get; set; }
public List<FrontPageProduct> InFrontPages { get; set; }
public List<ProductInCategory> InCategories { get; set; }
}
public class ProductCategory
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public int SortOrder { get; set; }
public string Title { get; set; }
[ForeignKey(nameof(ParentCategory))]
public int? ParentId { get; set; }
public ProductCategory ParentCategory { get; set; }
public ICollection<ProductCategory> Children { get; set; } = new List<ProductCategory>();
public List<ProductInCategory> ProductInCategory { get; set; }
}
public class FrontPageProduct
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public int ProductCategoryId { get; set; }
public int ProductId { get; set; }
public int SortOrder { get; set; }
[ForeignKey("ProductId")]
public virtual Product Product { get; set; }
[ForeignKey("ProductCategoryId")]
public virtual ProductCategory ProductCategory { get; set; }
}
fpp
对象的调试检查显示 ProductCategoryId
和 ProductId
的值是正确的:
哪里 is/are 我的 mistake/s?
EDIT 我将建议的 [Key]
和 [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
添加到所有模型,但我仍然遇到相同的错误。
我认为 Id
字段在 EF 中总是默认设置为主键。
EDIT 2 我尝试在我的控制器方法中添加 [FromBody]
,但这只会导致空白屏幕,没有错误消息,也没有对数据库。
编辑 3 我将 [ForeignKey("ProductId")]
和 [ForeignKey("ProductCategoryId")]
添加到 FrontPageProduct
模型,但仍然得到相同的 SqlException。
EDIT 4 这些是我的四个 table 的外键:
FrontPageProducts
:
FK_FrontPageProducts_ProductCategories_ProductCategoryId
FK_FrontPageProducts_Products_ProductId
ProductCategories
:
FK_ProductCategories_ProductCategories_ParentId
Products
:
none
ProductsInCategories
:
FK_ProductsInCategories_FrontPageProducts_FrontPageProductId
FK_ProductsInCategories_ProductCategories_ProductCategoryId
FK_ProductsInCategories_Products_ProductId
Id 字段应该是数据库中的主键,以便您可以在实体模型中指定它。 - 添加[密钥]
public class Product
{
[Key]
public int Id { get; set; }
public string Title { get; set; }
public string Info { get; set; }
public decimal Price { get; set; }
public IEnumerable<FrontPageProduct> InFrontPages { get; set; }
public List<ProductInCategory> InCategories { get; set; }
}
看起来您不需要为 "int Id" 字段设置 DatabaseGenerated 属性,这是一个约定并假设它是标识列。 顺便说一句,你确定你得到了同样的错误吗? imgur link 对我不起作用。您的 FrontPage 是否真的需要 Product 和 ProductCategory class,如果您可以轻松地将它们注释掉并进行测试,请这样做,如果不能,您可以尝试如下设置它们的值。
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> FrontPageProduct(ViewModelFrontPageProduct frontPageProduct)
{
var fpp = new FrontPageProduct()
{
ProductCategoryId = frontPageProduct.ProductCategoryId,
ProductId = frontPageProduct.ProductId,
Product = _context.Set<Product>().Find(frontPageProduct.ProductId),
ProductCategory = _context.Set<ProductCategory>().Find(frontPageProduct.ProductCategoryId),
SortOrder = 0
};
_context.Add(fpp);
await _context.SaveChangesAsync();
return View("Index", new { id = fpp.ProductCategoryId, tab = 2 });
}
将 Key 和 DatabaseGenerated 属性应用于模型中的每个 Id 列,以便 EF 知道它是一个标识列,并且需要取回生成的 id 值。
public class Product
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Title { get; set; }
public string Info { get; set; }
public decimal Price { get; set; }
[InverseProperty("Product")]
public IEnumerable<FrontPageProduct> InFrontPages { get; set; }
public List<ProductInCategory> InCategories { get; set; }
}
public class ProductCategory
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public int SortOrder { get; set; }
public string Title { get; set; }
[ForeignKey(nameof(ParentCategory))]
public int? ParentId { get; set; }
public ProductCategory ParentCategory { get; set; }
public ICollection<ProductCategory> Children { get; set; } = new List<ProductCategory>();
public List<ProductInCategory> ProductInCategory { get; set; }
}
public class FrontPageProduct
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public int ProductCategoryId { get; set; }
public int ProductId { get; set; }
public int SortOrder { get; set; }
[ForeignKey("ProductId")]
public virtual Product Product { get; set; }
[ForeignKey("ProductCategoryId ")]
public virtual ProductCategory ProductCategory { get; set; }
}
编辑:您应该添加导航属性,就像我在上面添加的那样。使它们虚拟化也有助于延迟加载。