【发布时间】:2016-06-18 09:49:27
【问题描述】:
我正在开发一个带有 Entity-Framework Core(版本 "EntityFramework.Core": "7.0.0-rc1-final")的 ASP.NET MVC 6 项目,该项目由 SQL Server 2012 express DB 提供支持。
我需要在 Person 实体和 Address 实体之间建模多对多关系。
根据this 指南,我使用PersonAddressjoin-table 实体对其进行建模,因为这样我可以存储一些额外的信息。
我的目标是以这种方式设置我的系统:
- 如果删除了
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() 将让数据库处理最终的 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 及其相关实体?
谢谢大家。
【问题讨论】:
标签: c# entity-framework ef-code-first code-first entity-framework-core