Tôi đang làm việc trên một dự án ASP.NET MVC 6 với Entity-Framework Core (phiên bản "EntityFramework.Core": "7.0.0-rc1-final"
) được hỗ trợ bởi một SQL Server 2012 Express DB.Cấu trúc thực thể Core Code-First: Cascade delete trên mối quan hệ nhiều-nhiều
Tôi cần lập mô hình mối quan hệ nhiều-nhiều giữa một thực thể Person
và thực thể Address
. Theo hướng dẫn của this tôi đã mô hình hóa nó với một thực thể kết hợp PersonAddress
, bởi vì theo cách này tôi có thể lưu trữ một số thông tin bổ sung.
Mục tiêu của tôi là để thiết lập hệ thống của tôi theo cách này:
- Nếu một trường hợp
Person
bị xóa, tất cả các liên quanPersonAddress
trường hợp phải được xóa. Tất cả các trường hợpAddress
mà chúng tham chiếu đến cũng phải bị xóa, chỉ khi chúng không liên quan đến các trường hợpPersonAddress
khác. - Nếu một phiên bản
PersonAddress
bị xóa, trường hợpAddress
liên quan đến nó phải bị xóa chỉ khi nó không liên quan đến các trường hợpPersonAddress
khác. Tất cả các trường hợpPerson
phải hoạt động. - Nếu một phiên bản
Address
bị xóa, tất cả các phiên bảnPersonAddress
liên quan phải được xóa. Tất cả các trường hợpPerson
phải hoạt động.
Tôi nghĩ hầu hết công việc phải được thực hiện trong mối quan hệ nhiều-nhiều giữa Person
và Address
, nhưng tôi cũng mong đợi viết một số logic. Tôi sẽ để phần này ra khỏi câu hỏi này. Những gì tôi quan tâm là làm thế nào để cấu hình mối quan hệ nhiều-nhiều của tôi.
Đây là tình huống hiện tại.
Đây là thực thể Person
. Xin lưu ý rằng thực thể này có mối quan hệ một-nhiều với các thực thể phụ khác.
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
}
Đây là thực thể 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
}
Đây là thực thể 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
}
Đây là thực thể DatabaseContext
, nơi tất cả các mối quan hệ được mô tả.
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();
}
}
Cả hai đối tượng Telephone
và City
đều đã bị xóa để đơn giản.
Đây là mã để xóa Person
.
Person person = await _context.People.SingleAsync(m => m.Id == id);
try
{
_context.People.Remove(person);
await _context.SaveChangesAsync();
}
catch (Exception ex)
{
}
Đối với bài đọc của tôi tránh .Include()
sẽ cho DB chăm sóc CASCADE
xóa cuối cùng. Tôi xin lỗi nhưng tôi không nhớ câu hỏi SO mà khái niệm này đã được làm rõ.
Nếu tôi chạy mã này, tôi có thể hạt giống DB bằng cách sử dụng this workaround.Khi tôi muốn kiểm tra-xóa một thực thể Person
với đoạn code trên, tôi nhận được ngoại lệ này:
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.
Tôi đã thử nghiệm một vài thiết lập mối quan hệ trong phương pháp DatabaseContext.OnModelCreating
mà không cần bất kỳ may mắn.
Cuối cùng, đây là câu hỏi của tôi. Tôi nên định cấu hình quan hệ nhiều-nhiều của mình như thế nào để xóa chính xác một số Person
và các thực thể liên quan khỏi ứng dụng của tôi, theo mục tiêu được mô tả trước đây?
Cảm ơn tất cả.