I know this question has been asked and answered a few times:
Specifying ON DELETE NO ACTION in Entity Framework 7?
Configuring cascade delete with EF7
But in my case I'm using SQLite and none of the solutions seem to work. Similar code to update the database works in EF6 on SQL Server, but unless I'm missing something really obvious, doesn't work on EF Core with SQLite on .NET Standard 2.0. I have a parent Customer with child Contacts and am saving them all at once.
using (var dbc = new ContactsDbContext())
{
var customer = dbc.Customers.First(s => s.CustomerID == ReadProperty(CustomerIDProperty).ToString());
foreach (var item in dbc.Contacts.Where(x => x.CustomerID == ReadProperty(CustomerIDProperty).ToString()))
{
dbc.Contacts.Remove(item);
}
MapToEntity(customer);
dbc.SaveChanges();
}
I get the following exception upon SaveChanges()
System.InvalidOperationException occurred HResult=0x80131509 Message=The instance of entity type 'Contact' cannot be tracked because another instance with the key value 'ContactID:99b44b3e-c981-4140-9198-b665d3d85600' is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached.
I loved having the ability to turn off cascade deletes globally in prior versions of EF. This is what used to work:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
}
And I've tried using these two solutions below, of which neither works for SQLite.
foreach (var relationship in modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys()))
{
// Also tried Cascade, and all other options
relationship.DeleteBehavior = DeleteBehavior.Restrict;
}
AND
modelBuilder.Entity<Entity.Contact>()
.HasOne(p => p.Customer)
.WithMany()
.HasForeignKey("CustomerID")
.OnDelete(DeleteBehavior.Restrict);
Has anyone successfully used parent/child updating on SQLite? My alternative is to manually check the status on each child object before saving, but that seems unnecessary for a feature that used to work. Thanks in advance for looking at this.
Here's my Contact and customer classes
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Contacts.Library.Data.Entity
{
[Serializable()]
public class Contact
{
[Key]
public int PrimaryKey { get; set; }
[Required, MaxLength(36)]
public string ContactID { get; set; }
[ForeignKey("CustomerID"), MaxLength(36)]
public string CustomerID { get; set; }
[MaxLength(50)]
public string Name { get; set; }
// Path back to related customer
public virtual Customer Customer { get; set; }
}
}
[Serializable()]
public class Customer
{
[Key]
public int PrimaryKey { get; set; }
[Required, MaxLength(36)]
public string CustomerID { get; set; }
[Required, MaxLength(50)]
public string Name { get; set; }
// A customer has a collection of contacts
public virtual ICollection<Contact> Contacts { get; set; }
}
And here's my indexes
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Name on customer is unique
modelBuilder.Entity<Entity.Customer>().HasIndex(c => c.Name).IsUnique();
// Add index
modelBuilder.Entity<Entity.Customer>().HasIndex(
customer => new { customer.CustomerID }).IsUnique(false);
// Add index
modelBuilder.Entity<Entity.Contact>().HasIndex(
contact => new { contact.ContactID }).IsUnique(false);
// Add index
modelBuilder.Entity<Entity.Contact>().HasIndex(
contact => new { contact.CustomerID }).IsUnique(false);
}
User contributions licensed under CC BY-SA 3.0