【问题标题】:Conventions.Remove<OneToManyCascadeDeleteConvention>() in EF Core?EF Core 中的 Conventions.Remove<OneToManyCascadeDeleteConvention>()?
【发布时间】:2018-03-04 02:57:02
【问题描述】:

在我的常规 .NET Framework 应用程序中,我使用的是 EF 6.x,并且还使用了一些继承,特别是:

PurchaseOrder.csSaleOrder.cs 都继承自 Order.cs

在继承自IdentityDbContext 的上下文类的OnModelCreating() 中,我正在做:

modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

这曾经可以工作,但现在我将我的应用程序移动到 .NET Core 2.0 并且我正在使用 EF Core。什么在 EF Core 中实现了同样的目标?因为现在我得到了错误:

System.Data.SqlClient.SqlException (0x80131904):在表“Order”上引入 FOREIGN KEY 约束“FK_Order_Business_CustomerId”可能会导致循环或多个级联路径。指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。

更新

这是 Ahmar 回答后的代码。在我的上下文类中,我有:

protected override void OnModelCreating(ModelBuilder builder)
{
  base.OnModelCreating(builder);
  builder.HasDefaultSchema("PD");

  builder.Entity<Customer>()
    .HasMany(c => c.SaleOrders)
    .WithOne(e => e.Customer)
    .OnDelete(DeleteBehavior.SetNull);

  builder.Entity<Supplier>()
    .HasMany(po => po.PurchaseOrders)
    .WithOne(e => e.Supplier)
    .OnDelete(DeleteBehavior.SetNull);

  builder.Entity<PurchaseOrder>()
    .HasMany(li => li.LineItems)
    .WithOne(po => po.PurchaseOrder)
    .OnDelete(DeleteBehavior.SetNull);

  builder.Entity<SaleOrder>()
    .HasMany(li => li.LineItems)
    .WithOne(po => po.SaleOrder)
    .OnDelete(DeleteBehavior.SetNull);
}

就实体而言,它们是:

public abstract class Business : IEntity
{
  protected Business()
  {
    CreatedOn = DateTime.UtcNow;
  }

  public int Id { get; set; }
  public string Name { get; set; }
  public string TaxNumber { get; set; }
  public string Description { get; set; }
  public string Phone { get; set; }
  public string Website { get; set; }
  public string Email { get; set; }
  public bool IsDeleted { get; set; }
  public DateTime CreatedOn { get; set; }
  public DateTime? ModifiedOn { get; set; }
  public ICollection<Address> Addresses { get; set; } = new List<Address>();
  public ICollection<Contact> Contacts { get; set; } = new List<Contact>();
}

[Table("Customers")]
public class Customer : Business
{
  public decimal AllowedCredit { get; set; }
  public decimal CreditUsed { get; set; }
  public int NumberOfDaysAllowedToBeOnMaxedOutCredit { get; set; }
  public ICollection<SaleOrder> SaleOrders { get; set; }
}

[Table("Suppliers")]
public class Supplier : Business
{
  public ICollection<PurchaseOrder> PurchaseOrders { get; set; }
}

public abstract class Order : IEntity
{
  protected Order()
  {
    Date = DateTime.UtcNow;
    CreatedOn = DateTime.UtcNow;
  }

  public int Id { get; set; }
  public DateTime Date { get; set; }
  public decimal ShippingCost { get; set; }
  public Currency ShippingCurrency { get; set; }
  public decimal ShippingConversionRate { get; set; }
  public bool IsDeleted { get; set; }
  public DateTime CreatedOn { get; set; }
  public DateTime? ModifiedOn { get; set; }
  public ICollection<Invoice> Invoices { get; set; }
  public ICollection<Note> Notes { get; set; }
}

[Table("PurchaseOrders")]
public class PurchaseOrder : Order
{
  public int SupplierOrderNumber { get; set; }
  public PurchaseOrderStatus Status { get; set; }
  public decimal Vat { get; set; }
  public decimal ImportDuty { get; set; }
  public int SupplierId { get; set; }
  public Supplier Supplier { get; set; }
  public ICollection<PurchaseOrderLineItem> LineItems { get; set; }
}

[Table("SaleOrders")]
public class SaleOrder : Order
{
  public decimal AmountToBePaidOnCredit { get; set; }
  public SaleOrderStatus Status { get; set; }
  public ICollection<SaleOrderLineItem> LineItems { get; set; }
  public int CustomerId { get; set; }
  public Customer Customer { get; set; }
}

所以在按照 Ahmar 的建议进行操作后,我在执行 update-database 时仍然遇到同样的错误。

【问题讨论】:

标签: c# asp.net-core entity-framework-core


【解决方案1】:

您需要在 .Net Core EF 中为每个实体配置级联删除行为。

Entity Framework Core Fluent API OnDelete 方法用于指定删除主体时应在关系中的依赖实体上执行的操作。

OnDelete 方法将DeleteBehavior 枚举作为参数:

  • 级联 - 应删除依赖项
  • 限制 - 家属是 不受影响
  • SetNull - 依赖行中的外键值应该 更新为 NULL

例子:

public class Company
{
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<Employee> Employees { get; set; }
}

public class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int? CompanyId { get; set; }
    public Company Company { get; set; }
}

protected override void OnModelCreating(Modelbuilder modelBuilder)
{
    modelBuilder.Entity<Company>()
        .HasMany(c => c.Employees)
        .WithOne(e => e.Company).
        .OnDelete(DeleteBehavior.SetNull);
}

删除Company时,会将Employee表中的CompanyId属性设置为null。

Configuring One To Many Relationships获取更多详细信息

PS.请确保您的所有引用属性都应为空,以便 EF Core 可以在删除时将它们设置为空。像CompanyId 的例子。

【讨论】:

  • 对不起@Ahmar,它编译了它,但是当我运行Update-Database 它仍然给我同样的错误。这里是the classes
  • 奇怪,抱歉我更新了问题以添加代码。
  • @Ciwan 您需要在 SaleOrder 和 PurchaseOrder 实体中使 SupplierId 和 CustomerId 可以为空。我也更新了我的答案。
  • 仍然没有用,即使在我制作它们 nullable 之后也是如此。我得到了同样的错误:/
  • 您在制作nullable 后是否创建了新的迁移?删除旧的迁移并添加新的然后尝试做update-database
猜你喜欢
  • 1970-01-01
  • 2019-01-21
  • 1970-01-01
  • 2019-05-02
  • 2018-04-19
  • 1970-01-01
  • 1970-01-01
  • 2019-05-06
  • 2020-03-29
相关资源
最近更新 更多