Conventions.Remove() in EF Core?

asp.net-core c# entity-framework-core

Question

In my regular .NET Framework application, I was using EF 6.x and was also using some Inheritance, specifically:

PurchaseOrder.cs and SaleOrder.cs both inherit from Order.cs

And in the OnModelCreating() on my context class inheriting from IdentityDbContext, I was doing:

modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

This used to work, but now I am moving my application to .NET Core 2.0 and I am using EF Core. What achieves the same thing in EF Core? Because right now I am getting the error:

System.Data.SqlClient.SqlException (0x80131904): Introducing FOREIGN KEY constraint 'FK_Order_Business_CustomerId' on table 'Order' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.

UPDATE

Here's the code after Ahmar's answer. In my context class, I have:

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);
}

And as far the Entities, they are:

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

So after doing what Ahmar suggested, I still get the same error when I do update-database.

1
0
3/3/2018 5:09:29 PM

Popular Answer

You need to configure cascade delete behavior on each entity in .Net Core EF.

The Entity Framework Core Fluent API OnDelete method is used to specify the action which should take place on a dependent entity in a relationship when the principal is deleted.

The OnDelete method takes a DeleteBehavior enum as a parameter:

  • Cascade - dependents should be deleted
  • Restrict - dependents are unaffected
  • SetNull - the foreign key values in dependent rows should update to NULL

Example:

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);
}

When deleting the Company, it will set CompanyId property in Employee table to null.

Get more detail at Configuring One To Many Relationships

PS. Please make sure your all referencing properties should be null able so, EF Core can set them null on delete. like CompanyId in about example.

1
3/3/2018 6:57:02 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow