添加行时获取 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 对象的调试检查显示 ProductCategoryIdProductId 的值是正确的:

哪里 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; }
    }

编辑:您应该添加导航属性,就像我在上面添加的那样。使它们虚拟化也有助于延迟加载。