0

I am a bit confused of how this cascading works. So I have these 2 entities linked together.

Sales Contract:

public class SalesContract : ObjectMapper
{
    [Key]
    [Index(IsUnique = true)]
    [AutoGenerated]
    public Guid ID { get; set; } = Guid.NewGuid();

    [Required]
    [Index(IsUnique = true)]
    [StringLength(50)]
    public string SCNo { get; set; }

    [Required]
    public string DeliveryAddress { get; set; }

    public DateTime DeliveryDate { get; set; } = DateTime.UtcNow;

    [Required]
    public string Transport { get; set; }

    [ForeignKey("PaymentMethod")]
    public Guid PaymentMethodId { get; set; }
    public virtual PaymentMethod PaymentMethod { get; set; }

    public int PaymentTime { get; set; }

    public string Note { get; set; }

    [ForeignKey("ItemType")]
    public Guid ItemTypeId { get; set; }
    public ItemType ItemType { get; set; }

    public Guid SalesId { get; set; }
    public virtual Account Sales { get; set; }

    [ForeignKey("Buyer")]
    public Guid BuyerId { get; set; }
    public virtual Buyer Buyer { get; set; }

    [Required]
    public string Status { get; set; } = "Pending"; //Pending / Approved

    public Guid? ApprovedById { get; set; }
    public virtual Account ApprovedBy { get; set; }

    public bool? IsApproved { get; set; }

    [AutoGenerated]
    public DateTime DateCreated { get; set; } = DateTime.UtcNow;

    public ICollection<SalesContractItem> Items { get; set; }

    public async Task<bool> Delete(MigrationDBContext db)
    {
        this.Items.ForEach(m => { db.SalesContractItems.Remove(m); });
        db.SalesContracts.Remove(this);
        await db.SaveChangesAsync();
        return true;
    }
}

And Sales Contract Item:

public class SalesContractItem : ObjectMapper
{
    [Key]
    [Index(IsUnique = true)]
    [AutoGenerated]
    public Guid ID { get; set; } = Guid.NewGuid();

    [ForeignKey("Item")]
    public Guid ItemId { get; set; }
    public virtual Item Item { get; set; }

    [ForeignKey("Color")]
    public Guid ColorId { get; set; }
    public virtual Color Color { get; set; }

    [ForeignKey("Unit")]
    public Guid UnitId { get; set; }
    public virtual Unit Unit { get; set; }

    [ForeignKey("ItemType")]
    public Guid ItemTypeId { get; set; }
    public virtual ItemType ItemType { get; set; }

    public decimal Price { get; set; }
    
    [ForeignKey("Currency")]
    public Guid CurrencyId { get; set; }
    public Currency Currency { get; set; }

    [Required]
    public decimal BaseQty { get; set; }
    public decimal Remaining { get; set; }

    public string Description { get; set; }

    [AutoGenerated]
    public DateTime DateCreated { get; set; } = DateTime.UtcNow;

    [ForeignKey("SalesContract")]
    public Guid SalesContractId { get; set; }
    public virtual SalesContract SalesContract { get; set; }

    public async Task<bool> Delete(MigrationDBContext db)
    {
        db.SalesContractItems.Remove(this);
        await db.SaveChangesAsync();
        return true;
    }
}

ObjectMapper class contains only functions, there is no entity property.

The full error message is this:

Introducing FOREIGN KEY constraint 'FK_dbo.SalesContractItems_dbo.SalesContracts_SalesContractId' on table 'SalesContractItems' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints. Could not create constraint or index. See previous errors.

What is wrong with these 2 entities which causes multiple cascading when delete?


NOTE

As requested these are the full entities linked to both.

public class Item : ObjectMapper
{
    [Key]
    [Index(IsUnique = true)]
    [AutoGenerated]
    public Guid ID { get; set; } = Guid.NewGuid();

    [Required]
    [Index(IsUnique = true)]
    [StringLength(50)]
    public string ItemName { get; set; }

    public async Task<bool> Delete(MigrationDBContext db)
    {
        db.Items.Remove(this);
        await db.SaveChangesAsync();
        return true;
    }
}

public class Color : ObjectMapper
{
    [Key]
    [Index(IsUnique = true)]
    [AutoGenerated]
    public Guid ID { get; set; } = Guid.NewGuid();

    [Required]
    [Index(IsUnique = true)]
    [StringLength(50)]
    public string ColorCode { get; set; }

    public string ColorName { get; set; }

    public async Task<bool> Delete(MigrationDBContext db)
    {
        db.Colors.Remove(this);
        await db.SaveChangesAsync();
        return true;
    }
}

public class Unit : ObjectMapper
{
    [Key]
    [Index(IsUnique = true)]
    [AutoGenerated]
    public Guid ID { get; set; } = Guid.NewGuid();

    [Required]
    [Index(IsUnique = true)]
    [StringLength(50)]
    public string UnitName { get; set; }

    public async Task<bool> Delete(MigrationDBContext db)
    {
        db.Units.Remove(this);
        await db.SaveChangesAsync();
        return true;
    }
}

public class ItemType : ObjectMapper
{
    [Key]
    [Index(IsUnique = true)]
    [AutoGenerated]
    public Guid ID { get; set; } = Guid.NewGuid();

    [Required]
    [Index(IsUnique = true)]
    [StringLength(50)]
    public string ItemTypeName { get; set; }

    public async Task<bool> Delete(MigrationDBContext db)
    {
        db.ItemTypes.Remove(this);
        await db.SaveChangesAsync();
        return true;
    }
}

public class PaymentMethod : ObjectMapper
{
    [Key]
    [Index(IsUnique = true)]
    [AutoGenerated]
    public Guid ID { get; set; } = Guid.NewGuid();

    [Required]
    public string PaymentMethodName { get; set; }

    public async Task<bool> Delete(MigrationDBContext db)
    {
        db.PaymentMethods.Remove(this);
        await db.SaveChangesAsync();
        return true;
    }
}

public class Currency : ObjectMapper
{
    [Key]
    [Index(IsUnique = true)]
    [AutoGenerated]
    public Guid ID { get; set; } = Guid.NewGuid();

    [Required]
    [Index(IsUnique = true)]
    [StringLength(50)]
    public string CurrencyName { get; set; }

    [Required]
    public string CurrencySymbol { get; set; }

    public async Task<bool> Delete(MigrationDBContext db)
    {
        db.Currencies.Remove(this);
        await db.SaveChangesAsync();
        return true;
    }
}
Alvin Stefanus
  • 1,873
  • 2
  • 22
  • 60
  • It means if you were to delete one of your records, its unknown how cascade delete should be performed and which path is the correct one, its ambiguous. since we cant see your complete model, its hard to help – TheGeneral Jul 30 '20 at 04:27
  • I have copied all of the entities, please kindly check sir @TheGeneral – Alvin Stefanus Jul 30 '20 at 04:58
  • Check [this](https://stackoverflow.com/questions/17127351/introducing-foreign-key-constraint-may-cause-cycles-or-multiple-cascade-paths) post. – Arsen Khachaturyan Jul 31 '20 at 19:17
  • I have to set the foreign key as nullable to make this work, then I was wondering if I set the foreign key as required, does the `willcascadeondelete(false)` work? Because if I tried to set it false, it does not work. – Alvin Stefanus Aug 02 '20 at 07:43

0 Answers0