我正在使用由SQL Server 2012 express数据库支持的Entity-Framework Core(版本号"EntityFramework.Core": "7.0.0-rc1-final"
)开发ASP.NET MVC 6项目。实体框架核心代码 - 第一:在多对多关系上级联删除
我需要建模一个Person
实体和一个Address
实体之间的多对多关系。 根据this指南,我使用PersonAddress
连接表实体对其进行建模,因为这样我可以存储一些额外的信息。
我目标是建立在我的系统是这样的:
- 如果
Person
实例被删除,所有相关PersonAddress
情况下,必须删除。它们所引用的所有Address
实例必须也被删除,前提是它们与其他PersonAddress
实例无关。 - 如果删除
PersonAddress
实例,则必须删除与其相关的Address
实例,只有当它与其他PersonAddress
实例无关。所有Person
实例都必须存在。 - 如果删除了一个
Address
实例,则必须删除所有相关的PersonAddress
实例。所有Person
实例都必须存在。
我想大多数的工作都必须在Person
和Address
之间的许多一对多的关系来完成的,但我希望能写一些逻辑了。我将把这一部分摆脱这个问题。我感兴趣的是如何配置我的多对多关系。
这是目前的情况。
这是Person
实体。请注意,此实体与其他辅助实体有一对多的关系。
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
}
这是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
}
这是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
}
这是DatabaseContext
实体,其中描述了所有的关系。
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();
}
}
Telephone
都和City
实体已经为简单起见移除。
这是删除Person
的代码。
Person person = await _context.People.SingleAsync(m => m.Id == id);
try
{
_context.People.Remove(person);
await _context.SaveChangesAsync();
}
catch (Exception ex)
{
}
至于我的读数避免.Include()
会让DB采取最终CASCADE
删除的照顾。我很抱歉,但我不记得这个概念澄清的SO问题。
如果我运行这段代码,我可以使用this workaround来播种数据库。当我想测试,删除Person
实体与上面的代码,我得到这个异常:
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.
我在DatabaseContext.OnModelCreating
方法测试了几种关系设置没有任何的运气。
最后,这是我的问题。根据前面描述的目标,我应该如何配置我的多对多关系以正确地从我的应用程序中删除Person
及其相关实体?
谢谢大家。