首页 文章

ef核心一对多关系抛出异常无法添加或更新子行

提问于
浏览
1

我的商店和产品实体有一对多关系,请查看我的模型

public class Product
{
   public int ID { get; set; }
   public string Name { get; set; }
   public string Tag { get; set; }
   public string Brand { get; set; }
   public string Place { get; set; }

   public int ShopID { get; set; }
   public Shop Shop { get; set; }
}

public class Shop
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Comment { get; set; }
    public string Number { get; set; }

    public ICollection<Product> Products { get; set; }
}



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

        public DbSet<Shop> Shops { get; set; }
        public DbSet<Product> Products { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Shop>().ToTable("shop");
            modelBuilder.Entity<Product>().ToTable("product");
        }

    }

public class CreateModel : PageModel
{
    private readonly ShopContext _context;

    public CreateModel(ShopContext context)
    {
        _context = context;
    }

    public IActionResult OnGet()
    {
        ViewData["Shop"] = new SelectList(_context.Shops, "ID", "Name");

        return Page();
    }

    [BindProperty]
    public Product Product { get; set; }

    public async Task<IActionResult> OnPostAsync()
    {
        if (!ModelState.IsValid)
        {
            return Page();
        }

        _context.Products.Add(Product);
        await _context.SaveChangesAsync();

        return RedirectToPage("./Index");
    }
}

创建页面中的商店是下拉列表,当我将新产品发布到处理程序时,我可以看到product.ShopID是Shop表中存在的ID,product.Shop.ID与product.ShopID相同 . 但是当我调用saveChangesAsync()时,它会抛出异常:

MySqlException:无法添加或更新子行:外键约束失败( shopdb . product ,CONSTRAINT FK_product_shop_ShopID FOREIGN KEY( ShopID )REFERENCES shopID )ON DELETE CASCADE)

我尝试在调用saveChangesAsync方法之前将product.Shop设置为null,但仍然无法工作,任何人都可以提供帮助吗?

ASP.NET Core 2.0 Razor Pages应用程序,Nuget:Pomelo.EntityFrameworkCore.MySql v2.0.1

2 回答

  • 1

    Product 表中将 ShopID 声明为可为空,您正在执行 product.Shop = null; ,因此它会尝试在此列中插入 ShopID value null . 由于 Product 表中的 ShopID 列不可为空,这就是它给出错误的原因 . 因为 Shop 表中没有 Id 可以为空 . 所以它给出 foreign key constraint fails 例外 . 所以你要做的就是使用像 public int? ShopID 这样可以为空的外键 .

  • 0

    如果设计要求,则不应使 ShopID 为空 .

    您遇到的问题是因为 Add 方法还递归地标记了所有可通过导航属性访问的实体实例,并且当前未被上下文跟踪为 Added (即new) .

    它可以通过多种方式解决:

    • 将实体条目设置为 Added 而不是 Add 方法:
    _context.Entry(Product).State = EntityState.Added;
    await _context.SaveChangesAsync();
    
    • 将导航属性设置为 null before ,调用 Add
    Product.Shop = null;
    _context.Products.Add(Product);
    await _context.SaveChangesAsync();
    
    • 附加导航属性对象 before 调用 Add
    if (Product.Shop != null) _context.Attach(Product.Shop);
    _context.Products.Add(Product);
    await _context.SaveChangesAsync();
    
    • 使用 Update 而不是 Add
    _context.Products.Update(Product);
    await _context.SaveChangesAsync();
    

    最后一种技术在_1380213中解释:

    使用自动生成的密钥,更新可以再次用于插入和更新,即使图形包含需要插入的实体和需要更新的实体的混合

    由于它仅在所有实体使用自动生成的PK时起作用,并且还产生相关实体的不必要更新,因此我不推荐它 .

相关问题