【发布时间】:2017-08-11 05:52:47
【问题描述】:
我正在尝试使用 Entity Framework Core
为产品变体数据库设计建模设计面临的问题/阻碍:
- 我在运行
dotnet ef migrations add InitialCreate命令时收到以下错误:
在表“ProductSKUValues”上引入 FOREIGN KEY 约束“FK_ProductSKUValues_ProductSKUs_ProductId_SkuId”可能会导致循环或多个级联路径。指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。 无法创建约束或索引。
数据库设计:
注意:此设计基于此链接建模:Modeling Product Variants
ApplicationDbContext.cs 与 Fluent API(注意 ProductSKU & ProductSKUValue 关系):
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using TikkyBoxWebAPI.Models.Account;
using TikkyBoxWebAPI.Models;
using TikkyBoxWebAPI.Models.Core;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
using System.Linq;
namespace TikkyBoxWebAPI.Data
{
public class TikkyBoxDbContext : DbContext
{
public TikkyBoxDbContext(DbContextOptions<TikkyBoxDbContext> options)
: base(options)
{
Database.Migrate();
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<ProductSKU>()
.HasKey(p => new { p.ProductId, p.SkuId });
modelBuilder
.Entity<ProductSKU>()
.HasOne(p => p.Product)
.WithMany(ps => ps.ProductSKUs)
.HasForeignKey(x => x.ProductId);
modelBuilder
.Entity<ProductSKU>()
.HasIndex(p => p.Sku);
modelBuilder
.Entity<ProductSKU>()
.Property(p => p.SkuId).ValueGeneratedOnAdd();
modelBuilder
.Entity<ProductSKUValue>()
.HasOne<ProductSKU>()
.WithMany( p => p.ProductSKUValues)
.IsRequired(false)
.OnDelete(DeleteBehavior.Restrict);
modelBuilder
.Entity<ProductSKUValue>()
.HasKey(p => new { p.ProductId, p.SkuId, p.OptionId});
modelBuilder
.Entity<ProductSKUValue>()
.HasOne(p => p.ProductOptionValue)
.WithMany(ps => ps.ProductSKUValues)
.HasForeignKey(x => new { x.ProductId, x.OptionId, x.ValueId })
.OnDelete(DeleteBehavior.Restrict);
modelBuilder
.Entity<ProductSKUValue>()
.HasOne(p => p.ProductOption)
.WithMany(ps => ps.ProductSKUValues)
.HasForeignKey(x => new { x.ProductId, x.OptionId })
.OnDelete(DeleteBehavior.Restrict);
modelBuilder
.Entity<ProductOptionValue>()
.HasKey(p => new { p.ProductId, p.OptionId, p.ValueId });
modelBuilder
.Entity<ProductOptionValue>()
.HasOne(p => p.ProductOption)
.WithMany(ps => ps.ProductOptionValues)
.HasForeignKey(x => new { x.ProductId, x.OptionId });
// .OnDelete(DeleteBehavior.Restrict);
modelBuilder
.Entity<ProductOptionValue>()
.Property(p => p.ValueId).ValueGeneratedOnAdd();
modelBuilder
.Entity<ProductOption>()
.HasKey(p => new { p.ProductId, p.OptionId });
modelBuilder
.Entity<ProductOption>()
.HasOne(p => p.Product)
.WithMany(po => po.ProductOptions)
.HasForeignKey(x => new { x.ProductId })
.OnDelete(DeleteBehavior.Restrict);
modelBuilder
.Entity<ProductOption>()
.Property(p => p.OptionId).ValueGeneratedOnAdd();
// base.OnModelCreating(modelBuilder);
}
public DbSet<Product> Products { get; set; }
public DbSet<ProductOption> ProductOptions { get; set; }
public DbSet<ProductOptionValue> ProductOptionValues { get; set; }
public DbSet<ProductSKU> ProductSKUs { get; set; }
public DbSet<ProductSKUValue> ProductSKUValues { get; set; }
}
}
Product.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace TikkyBoxWebAPI.Models.Core
{
public class Product
{
public int Id { get; set; }
[Required]
public String Name { get; set; }
// to be used for barcode : remember look at datatype
[MaxLength(32)]
public String UniversalProductCode { get; set; }
public Decimal Height { get; set; }
public Decimal Weight { get; set; }
public Decimal NetWeight { get; set; }
public Decimal Depth { get; set; }
[MaxLength(128)]
public String ShortDescription { get; set; }
[MaxLength(255)]
public String LongDescription { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime UpdatedOn { get; set; }
public virtual ICollection<ProductSKU> ProductSKUs { get; set; }
public virtual ICollection<ProductOption> ProductOptions { get; set; }
}
}
ProductSKU.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace TikkyBoxWebAPI.Models.Core
{
public class ProductSKU
{
public int ProductId { get; set; }
public int SkuId { get; set; }
[Required]
[MaxLength(64)]
public String Sku { get; set; }
public Product Product { get; set; }
public List<ProductSKUValue> ProductSKUValues { get; set; }
}
}
ProductSKUValue.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace TikkyBoxWebAPI.Models.Core
{
public class ProductSKUValue
{
public int ProductId { get; set; }
public int SkuId { get; set; }
public int OptionId { get; set; }
public int ValueId { get; set; }
public virtual ProductSKU ProductSKU { get; set; }
public virtual ProductOption ProductOption { get; set; }
public virtual ProductOptionValue ProductOptionValue { get; set; }
}
}
ProductOption.cs
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System;
namespace TikkyBoxWebAPI.Models.Core
{
public class ProductOption
{
public int ProductId { get; set; }
public int OptionId { get; set; }
[Required]
[MaxLength(40)]
public String OptionName { get; set; }
public virtual Product Product { get; set; }
public virtual ICollection<ProductSKUValue> ProductSKUValues { get; set; }
public virtual ICollection<ProductOptionValue> ProductOptionValues { get; set; }
}
}
ProductOptionValue.cs
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System;
namespace TikkyBoxWebAPI.Models.Core
{
public class ProductOptionValue
{
public int ProductId { get; set; }
public int ValueId { get; set; }
public int OptionId { get; set; }
[Required]
[MaxLength(32)]
public String ValueName { get; set; }
public virtual ProductOption ProductOption { get; set; }
public virtual ICollection<ProductSKUValue> ProductSKUValues { get; set; }
}
}
我已经在 StackOverflow 和网络上尝试了这些答案,但没有成功:
- Configuring Many to Many in Entity Framework Core
- Docs: Entity Framework Core Relationships
- EF One-To-Many - may cause cycles or multiple cascade paths Ef 4 Solution with nullable primary key (which I have tried)
我正在使用
- Microsoft.EntityFrameworkCore.SqlServer
- Microsoft.EntityFrameworkCore.Design
- Microsoft.AspNetCore.Identity.EntityFrameworkCore 版本 1.1.2
任何帮助将不胜感激。我已经在网上搜索了 2 天的解决方案
【问题讨论】:
-
为了获得帮助,去掉代码截图,添加所有涉及实体的实际代码(毕竟只有5个)和相关的fluent配置。
-
@IvanStoev 好吧,不仅有 5 个实体,还有更多。但我将删除其他关系和模型并隔离最小的
-
那将是完美的。所示模型肯定包含多个级联路径,仅隔离这些实体将有助于重现问题并确定问题是由它们还是由其他原因引起的。
-
@IvanStoev,我已经更新了所有相关实体
-
朋友,请张贴代码,而不是图片。这对您来说应该更容易,我们也可以在测试环境中复制/粘贴它。
标签: c# entity-framework asp.net-core asp.net-core-mvc entity-framework-core