C# ASP.NET MVC级联删除
我有两个模型。 城镇: 使用命令更新数据库后,出现下一个错误: 在表“TownDistricts”上引入外键约束“FK_dbo.TownDistricts_dbo.Districts_District_ID”可能会导致循环或多个级联路径。指定“在删除时不执行操作”或“在更新时不执行操作”,或修改其他外键约束 我看到了这个链接: 引用解决方案:C# ASP.NET MVC级联删除,c#,entity-framework,asp.net-mvc-5,C#,Entity Framework,Asp.net Mvc 5,我有两个模型。 城镇: 使用命令更新数据库后,出现下一个错误: 在表“TownDistricts”上引入外键约束“FK_dbo.TownDistricts_dbo.Districts_District_ID”可能会导致循环或多个级联路径。指定“在删除时不执行操作”或“在更新时不执行操作”,或修改其他外键约束 我看到了这个链接: 引用解决方案: protected override void OnModelCreating(DbModelBuilder modelBuilder)
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Town>().HasRequired(t => t.Districts).WithMany().WillCascadeOnDelete(false);
modelBuilder.Entity<District>().HasRequired(d => d.Towns).WithMany().WillCascadeOnDelete(false);
}
您必须至少在一个实体中使阶段成为可选的(即从阶段属性中删除[Required]属性)
但我没有[必需]属性。
我还尝试了这个解决方案:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Town>().HasRequired(t => t.Districts).WithMany().WillCascadeOnDelete(false);
modelBuilder.Entity<District>().HasRequired(d => d.Towns).WithMany().WillCascadeOnDelete(false);
}
但我找不到开发人员是如何在模型或其他方面解决这个问题的
谢谢你的帮助 根据需要,您不需要显式外键声明public int?TownID{get;set;}
在classDistrict
中,反之亦然(在另一个类中)。实体框架似乎能够配置所有必要的连接(数据库中的附加表),只需使用声明的导航集合,如publicvirtualicollection{get;set;}
添加。当声明两个单一属性public int时,您的意思是什么?DistrictID{get;set;}
和集合公共虚拟ICollection Districts{get;set;}
。您是否混淆了EF中多对多关系的概念,或者您的意思是这些属性表示不同的东西?如果它们表示不同的内容,那么您应该使用fluentapi来正确配置它们
更新。OP澄清后,我建议使用以下代码
public class TestEfContext : ApplicationDbContext {
public DbSet<Town> Towns { get; set; }
public DbSet<District> Districts { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Town>()
.HasMany<District>(x => x.Districts)
.WithOptional(x => x.Town);
modelBuilder.Entity<District>()
.HasMany<Town>(x => x.Towns)
.WithOptional(x => x.District);
}
}
public class Town {
[Key]
public int Id { get; set; }
public District District { get; set; }
public virtual ICollection<District> Districts { get; set; }
public override string ToString() {
return Id.ToString();
}
}
public class District {
[Key]
public int Id { get; set; }
public Town Town { get; set; }
public virtual ICollection<Town> Towns { get; set; }
public override string ToString() {
return Id.ToString();
}
}
这意味着Town1将有District=District1和empty Districts集合,而District1将有Town=null和Towns集合,其中有一个元素-Town1。因此,解决我的第一个问题和上面消息中的问题的最终类是:
namespace CpuRegistry.DataContexts
{
public class CpuRegistryDb : IdentityDbContext<ApplicationUser>
{
public CpuRegistryDb()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public static CpuRegistryDb Create()
{
return new CpuRegistryDb();
}
public DbSet<Region> Regions { get; set; }
public DbSet<District> Districts { get; set; }
public DbSet<Town> Towns { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Town>().HasMany<District>(t => t.Districts).WithOptional(d => d.Town);
modelBuilder.Entity<District>().HasMany<Town>(d => d.Towns).WithOptional(t => t.District);
}
}
}
namespace CpuRegistry.Models
{
public enum TownType
{
Город, Посёлок, Село
}
public class Town
{
public int ID { get; set; }
[Required]
public string Name { get; set; }
[Required]
public int RegionID { get; set; }
public int? DistrictID { get; set; }
[Required]
public TownType TownType { get; set; }
public virtual ICollection<District> Districts { get; set; }
public virtual Region Region { get; set; }
public virtual District District { get; set; }
public override string ToString()
{
return ID.ToString();
}
}
public class District
{
public int ID { get; set; }
[Required]
public string Name { get; set; }
[Required]
public int RegionID { get; set; }
public int? TownID { get; set; }
public virtual ICollection<Town> Towns { get; set; }
public virtual Region Region { get; set; }
public virtual Town Town { get; set; }
public override string ToString()
{
return ID.ToString();
}
}
}
namespace CpuRegistry.DataContexts
{
公共类CpuRegistryDb:IdentityDbContext
{
公共CpuRegistryDb()
:base(“DefaultConnection”,throwifvv1schema:false)
{
}
公共静态CpuRegistryDb Create()
{
返回新的CpuRegistryDb();
}
公共数据库集区域{get;set;}
公共数据库集区域{get;set;}
公共数据库集{get;set;}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
基于模型创建(modelBuilder);
modelBuilder.Entity()有许多(t=>t.Districts)。可选(d=>d.Town);
modelBuilder.Entity()有许多(d=>d.Towns)。带有可选(t=>t.District);
}
}
}
命名空间CpuRegistry.Models
{
公共枚举类型
{
Город, Посёлок, Село
}
公营城镇
{
公共int ID{get;set;}
[必需]
公共字符串名称{get;set;}
[必需]
public int RegionID{get;set;}
公共int?DistrictID{get;set;}
[必需]
公共TownType TownType{get;set;}
公共虚拟ICollection区域{get;set;}
公共虚拟区域{get;set;}
公共虚拟区区{get;set;}
公共重写字符串ToString()
{
返回ID.ToString();
}
}
公营学区
{
公共int ID{get;set;}
[必需]
公共字符串名称{get;set;}
[必需]
public int RegionID{get;set;}
公共int?TownID{get;set;}
公共虚拟ICollection{get;set;}
公共虚拟区域{get;set;}
公共虚拟城镇{get;set;}
公共重写字符串ToString()
{
返回ID.ToString();
}
}
}
谢谢@Hoborg的帮助。
public int?DistrictID
表示该城镇可以属于District(是District的一部分)<代码>公共虚拟ICollection Districts意味着该城镇可以有地区。在人类语言中:地区由城镇和地区划分。通常,该地区包括许多城镇。但有些大城镇不属于任何地区,而是按地区划分的@SergeyShambal在你解释之后,我更新了我的答案。这就是你需要的东西吗?如果是,那么你不认为这样的设计(一对多和反向多对一)看起来不太好吗?我尝试了你的解决方案,结果看起来像我需要的。非常感谢你。是的,我认为这样的设计不是一个好主意。但我上一条信息中的图表来自现实生活,我不知道如何用另一种方式来描述它。经过几天的开发,我遇到了一些问题。当我需要通过DropDownList设置Town-in-District模型时,该模型不会通过验证,因为DropDownList包含城镇的ID,但该模型等待完整类别的城镇。我将您的解决方案与我以前的变体相结合。我的下一个答案就是结果。
CreateTable(
"dbo.AspNetUserRoles",
c => new
{
UserId = c.String(nullable: false, maxLength: 128),
RoleId = c.String(nullable: false, maxLength: 128),
})
.PrimaryKey(t => new { t.UserId, t.RoleId })
.ForeignKey("dbo.AspNetRoles", t => t.RoleId, cascadeDelete: true)
.ForeignKey("dbo.AspNetUsers", t => t.UserId, cascadeDelete: true)
.Index(t => t.UserId)
.Index(t => t.RoleId);
public class TestEfContext : ApplicationDbContext {
public DbSet<Town> Towns { get; set; }
public DbSet<District> Districts { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Town>()
.HasMany<District>(x => x.Districts)
.WithOptional(x => x.Town);
modelBuilder.Entity<District>()
.HasMany<Town>(x => x.Towns)
.WithOptional(x => x.District);
}
}
public class Town {
[Key]
public int Id { get; set; }
public District District { get; set; }
public virtual ICollection<District> Districts { get; set; }
public override string ToString() {
return Id.ToString();
}
}
public class District {
[Key]
public int Id { get; set; }
public Town Town { get; set; }
public virtual ICollection<Town> Towns { get; set; }
public override string ToString() {
return Id.ToString();
}
}
using (var ctx = new TestEfContext()) {
ctx.Towns.First().District = ctx.Districts.First();
}
namespace CpuRegistry.DataContexts
{
public class CpuRegistryDb : IdentityDbContext<ApplicationUser>
{
public CpuRegistryDb()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public static CpuRegistryDb Create()
{
return new CpuRegistryDb();
}
public DbSet<Region> Regions { get; set; }
public DbSet<District> Districts { get; set; }
public DbSet<Town> Towns { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Town>().HasMany<District>(t => t.Districts).WithOptional(d => d.Town);
modelBuilder.Entity<District>().HasMany<Town>(d => d.Towns).WithOptional(t => t.District);
}
}
}
namespace CpuRegistry.Models
{
public enum TownType
{
Город, Посёлок, Село
}
public class Town
{
public int ID { get; set; }
[Required]
public string Name { get; set; }
[Required]
public int RegionID { get; set; }
public int? DistrictID { get; set; }
[Required]
public TownType TownType { get; set; }
public virtual ICollection<District> Districts { get; set; }
public virtual Region Region { get; set; }
public virtual District District { get; set; }
public override string ToString()
{
return ID.ToString();
}
}
public class District
{
public int ID { get; set; }
[Required]
public string Name { get; set; }
[Required]
public int RegionID { get; set; }
public int? TownID { get; set; }
public virtual ICollection<Town> Towns { get; set; }
public virtual Region Region { get; set; }
public virtual Town Town { get; set; }
public override string ToString()
{
return ID.ToString();
}
}
}