Sto lavorando a un progetto ASP.NET MVC 6 con Entity-Framework Core (versione "EntityFramework.Core": "7.0.0-rc1-final"
) supportato da un DB Express di SQL Server 2012.Codice nucleo di Entity Framework: prima eliminazione in cascata su una relazione molti-a-molti
Ho bisogno di modellare una relazione molti-a-molti tra un'entità Person
e un'entità Address
. Come da guida this l'ho modellato con un'entità join-table PersonAddress
, perché in questo modo posso memorizzare alcune informazioni extra.
Il mio obiettivo è di set-up il mio sistema in questo modo:
- Se un'istanza
Person
viene eliminato, tutti i relativiPersonAddress
casi deve essere cancellato. È necessario eliminare anche tutte le istanze diAddress
a cui fanno riferimento, solo se non sono correlate ad altre istanze diPersonAddress
. - Se un'istanza
PersonAddress
viene cancellata, l'istanzaAddress
a cui si riferisce deve essere cancellata solo se non è collegata ad altre istanzePersonAddress
. Tutte le istanzePerson
devono vivere. - Se un'istanza
Address
viene cancellata, tutte le relative istanzePersonAddress
devono essere eliminate. Tutte le istanzePerson
devono vivere.
penso la maggior parte del lavoro deve essere fatto in molti-a-molti tra Person
e Address
, ma mi aspetto di scrivere una logica troppo. Lascerò questa parte fuori da questa domanda. Quello che mi interessa è come configurare la mia relazione molti-a-molti.
Questa è la situazione attuale .
Questa è l'entità Person
. Si noti che questa entità ha relazioni uno-a-molti con altre entità secondarie.
public class Person
{
public int Id {get; set; } //PK
public virtual ICollection<Telephone> Telephones { get; set; } //navigation property
public virtual ICollection<PersonAddress> Addresses { get; set; } //navigation property for the many-to-many relationship
}
Questa è l'entità Address
.
public class Address
{
public int Id { get; set; } //PK
public int CityId { get; set; } //FK
public City City { get; set; } //navigation property
public virtual ICollection<PersonAddress> People { get; set; } //navigation property
}
Questa è l'entità PersonAddress
.
public class PersonAddress
{
//PK: PersonId + AddressId
public int PersonId { get; set; } //FK
public Person Person {get; set; } //navigation property
public int AddressId { get; set; } //FK
public Address Address {get; set; } //navigation property
//other info removed for simplicity
}
Questa è la DatabaseContext
entità, in cui sono descritte tutte le relazioni.
public class DataBaseContext : DbContext
{
public DbSet<Person> People { get; set; }
public DbSet<Address> Addresses { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
//All the telephones must be deleteded alongside a Person.
//Deleting a telephone must not delete the person it refers to.
builder.Entity<Person>()
.HasMany(p => p.Telephones)
.WithOne(p => p.Person);
//I don't want to delete the City when I delete an Address
builder.Entity<Address>()
.HasOne(p => p.City)
.WithMany(p => p.Addresses)
.IsRequired().OnDelete(Microsoft.Data.Entity.Metadata.DeleteBehavior.Restrict);
//PK for the join entity
builder.Entity<PersonAddress>()
.HasKey(x => new { x.AddressId, x.PersonId });
builder.Entity<PersonAddress>()
.HasOne(p => p.Person)
.WithMany(p => p.Addresses)
.IsRequired();
builder.Entity<PersonAddress>()
.HasOne(p => p.Address)
.WithMany(p => p.People)
.IsRequired();
}
}
Sia Telephone
e City
entità sono state rimosse per semplicità.
Questo è il codice per la rimozione di Person
.
Person person = await _context.People.SingleAsync(m => m.Id == id);
try
{
_context.People.Remove(person);
await _context.SaveChangesAsync();
}
catch (Exception ex)
{
}
Per quanto riguarda le mie letture, evitando .Include()
farà si che il DB prendersi cura degli eventuali CASCADE
eliminazioni. Mi dispiace ma non ricordo la domanda SO in cui questo concetto è stato chiarito.
Se si esegue questo codice, è possibile inizializzare il DB utilizzando this workaround.Quando voglio testare-eliminazione di un'entità Person
con il codice di cui sopra, ottengo questa eccezione:
The DELETE statement conflicted with the REFERENCE constraint "FK_PersonAddress_Person_PersonId". The conflict occurred in database "<dbName>", table "<dbo>.PersonAddress", column 'PersonId'.
The statement has been terminated.
ho provato diverse configurazioni relazionali nel metodo DatabaseContext.OnModelCreating
senza alcuna fortuna.
Infine, ecco la mia domanda . Come dovrei configurare la mia relazione molti-a-molti al fine di eliminare correttamente un Person
e le sue entità correlate dalla mia applicazione, secondo l'obiettivo descritto in precedenza ?
Grazie a tutti.