Sto utilizzando il codice TPT prima in Entity Framework 6 e ho la seguente configurazione:
public abstract class Product
{
[Key]
public string ProductID { get; set; }
// a bunch of trivial properties like dates and floats
}
[Table("SpecialProducts")]
public class SpecialProduct : Product
{
// more trivial properties
public List<Property> MyProperties { get; set; }
}
public class Property
{
[Key]
public int ID { get; set; }
[Required]
public SpecialProduct Product { get; set; }
// property data
}
public class MyDbContext : DbContext
{
public DbSet<Product> AllProducts { get; set; }
public MyDbContext()
: base("MyDataBase")
{}
public RemoveSomeProducts()
{
var products = from product in AllProducts where /* some condition */ select product;
AllProducts.RemoveRange(products);
SaveChanges();
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// I know I don't need both statements, and my guess is I need the first, but at this point I don't know anything anymore
modelBuilder.Entity<Property>()
.HasRequired(property => property.Product)
.WithMany(product => product.MyProperties)
.WillCascadeOnDelete(true);
modelBuilder.Entity<SpecialProduct>()
.HasMany(product => product.MyProperties)
.WithRequired(property => property.Product)
.WillCascadeOnDelete(true);
}
}
Quando si chiama RemoveSomeProducts()
ottengo la seguente eccezione:
SqlException: l'istruzione DELETE è in conflitto con il vincolo REFERENCE "FK_dbo.Properties_dbo.SpecialProducts_Product_ProductID". Il conflitto si è verificato nel database "MyDataBase", nella tabella "dbo.Properties", nella colonna "Product_ProductID".
A me sembra che le Properties
appartenenti agli SpecialProducts
cancellati non vengano eliminate. Ho poca esperienza con i database, ma dalla mia comprensione questo dovrebbe essere risolto usando l'eliminazione a cascata, ma mi sembra di non riuscire a configurarlo.
Quindi la mia domanda è ovviamente: come posso risolvere questo?
Potenziali duplicati che non sembrano essere d'aiuto nel mio caso, ma potrebbero essere utili per qualcun altro:
Prima di tutto è necessario includere esplicitamente la proprietà di navigazione nella query. Che per qualche ragione RemoveRange
non funziona come previsto con l'eliminazione a cascata, ma se si itera e si rimuove uno per uno funziona.
var products = Set<SpecialProduct>().Include(p => p.MyProperties).ToList();
products.ForEach(p => AllProducts.Remove(p));
SaveChanges();