Asp.net 实体框架:如何解决;外键约束可能导致循环或多个级联路径“;?
关于这个问题有很多问题,但我无法解决我的问题。 请大家看看这个: 我有一个Asp.net 实体框架:如何解决;外键约束可能导致循环或多个级联路径“;?,asp.net,entity-framework,sqlmembershipprovider,Asp.net,Entity Framework,Sqlmembershipprovider,关于这个问题有很多问题,但我无法解决我的问题。 请大家看看这个: 我有一个办公室表,它与医生和秘书表有一个多关系。最后两个表都派生自Employee表,该表与由sqlmembershipprovider创建的预定义Users表具有共享主键关系。似乎在用户表和角色表之间有很多关系,我没有参与其中 我的问题是在我的Employee表和该Users表之间创建一个(零,一)-(一)关系,我以它们之间的共享主键关系结束,然后引发错误。(有更好的解决方案吗?) 错误如下: public class Offi
办公室
表,它与医生
和秘书
表有一个多关系。最后两个表都派生自Employee
表,该表与由sqlmembershipprovider
创建的预定义Users
表具有共享主键关系。似乎在用户
表和角色
表之间有很多关系,我没有参与其中
我的问题是在我的Employee
表和该Users
表之间创建一个(零,一)-(一)关系,我以它们之间的共享主键关系结束,然后引发错误。(有更好的解决方案吗?)
错误如下:
public class Office
{
public Office()
{
this.Doctors = new HashSet<Doctor>();
this.Secretaries = new HashSet<Secretary>();
}
[Key]
public System.Guid OfficeId { get; set; }
public virtual ICollection<Doctor> Doctors { get; set; }
public virtual ICollection<Secretary> Secretaries { get; set; }
}
public class Employee
{
[Key, ForeignKey("User")]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public System.Guid Id { get; set; }
public string Name { get; set; }
[ForeignKey("Office")]
public System.Guid OfficeId { get; set; }
// shared primary key
public virtual aspnet_Users User { get; set; }
public virtual Office Office { get; set; }
}
public class Doctor :Employee
{
public Doctor()
{
this.Expertises = new HashSet<Expertise>();
}
//the rest..
public virtual ICollection<Expertise> Expertises { get; set; }
}
public class Secretary : Employee
{
// blah blah
}
public class aspnet_Users
{
public aspnet_Users()
{
this.aspnet_Roles = new List<aspnet_Roles>();
}
public System.Guid ApplicationId { get; set; }
public System.Guid UserId { get; set; }
//the rest..
public virtual aspnet_Applications aspnet_Applications { get; set; }
public virtual ICollection<aspnet_Roles> aspnet_Roles { get; set; }
}
public class aspnet_Roles
{
public aspnet_Roles()
{
this.aspnet_Users = new List<aspnet_Users>();
}
public System.Guid ApplicationId { get; set; }
public System.Guid RoleId { get; set; }
//the rest..
public virtual aspnet_Applications aspnet_Applications { get; set; }
public virtual ICollection<aspnet_Users> aspnet_Users { get; set; }
}
引入外键约束
表上的“FK_dbo.aspnet_UsersInRoles_dbo.aspnet_Users_UserId”
“aspnet_UsersInRoles”可能导致循环或多个级联路径。
指定在删除时不执行操作或在更新时不执行操作,或修改其他
外键约束。无法创建约束。见前文
错误
以下是逆向工程后我的代码和会员代码:
public class Office
{
public Office()
{
this.Doctors = new HashSet<Doctor>();
this.Secretaries = new HashSet<Secretary>();
}
[Key]
public System.Guid OfficeId { get; set; }
public virtual ICollection<Doctor> Doctors { get; set; }
public virtual ICollection<Secretary> Secretaries { get; set; }
}
public class Employee
{
[Key, ForeignKey("User")]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public System.Guid Id { get; set; }
public string Name { get; set; }
[ForeignKey("Office")]
public System.Guid OfficeId { get; set; }
// shared primary key
public virtual aspnet_Users User { get; set; }
public virtual Office Office { get; set; }
}
public class Doctor :Employee
{
public Doctor()
{
this.Expertises = new HashSet<Expertise>();
}
//the rest..
public virtual ICollection<Expertise> Expertises { get; set; }
}
public class Secretary : Employee
{
// blah blah
}
public class aspnet_Users
{
public aspnet_Users()
{
this.aspnet_Roles = new List<aspnet_Roles>();
}
public System.Guid ApplicationId { get; set; }
public System.Guid UserId { get; set; }
//the rest..
public virtual aspnet_Applications aspnet_Applications { get; set; }
public virtual ICollection<aspnet_Roles> aspnet_Roles { get; set; }
}
public class aspnet_Roles
{
public aspnet_Roles()
{
this.aspnet_Users = new List<aspnet_Users>();
}
public System.Guid ApplicationId { get; set; }
public System.Guid RoleId { get; set; }
//the rest..
public virtual aspnet_Applications aspnet_Applications { get; set; }
public virtual ICollection<aspnet_Users> aspnet_Users { get; set; }
}
公共班级办公室
{
公职()
{
this.Doctors=newhashset();
this.secretries=newhashset();
}
[关键]
public System.Guid OfficeId{get;set;}
公共虚拟ICollection{get;set;}
公共虚拟ICollection{get;set;}
}
公营雇员
{
[密钥,外国密钥(“用户”)]
[数据库生成(DatabaseGeneratedOption.None)]
public System.Guid Id{get;set;}
公共字符串名称{get;set;}
[外键(“办公室”)]
public System.Guid OfficeId{get;set;}
//共享主键
公共虚拟aspnet_用户用户{get;set;}
公共虚拟办公室{get;set;}
}
公立医生:雇员
{
公立医生()
{
this.experties=new HashSet();
}
//其余的。。
公共虚拟ICollection专家{get;set;}
}
公开课秘书:雇员
{
//废话
}
公共类aspnet_用户
{
公共aspnet_用户()
{
this.aspnet_Roles=新列表();
}
public System.Guid ApplicationId{get;set;}
public System.Guid用户标识{get;set;}
//其余的。。
公共虚拟aspnet_应用程序aspnet_应用程序{get;set;}
公共虚拟ICollection aspnet_角色{get;set;}
}
公共类aspnet\u角色
{
公共aspnet_角色()
{
this.aspnet_Users=新列表();
}
public System.Guid ApplicationId{get;set;}
public System.Guid RoleId{get;set;}
//其余的。。
公共虚拟aspnet_应用程序aspnet_应用程序{get;set;}
公共虚拟ICollection aspnet_用户{get;set;}
}
编辑:而且关系更深入,
用户
表格和应用程序
表格之间存在多个一的关系,角色
和应用程序
之间也存在多个一的关系。您可以使用fluent api指定错误消息建议的操作
在你的背景下:
protected override void OnModelCreating( DbModelBuilder modelBuilder )
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<aspnet_UsersInRoles>().HasMany(i => i.Users).WithRequired().WillCascadeOnDelete(false);
}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
基于模型创建(modelBuilder);
根据您的评论,问题在于您在两个表中使用了相同的PK。
我会马上改变它,让用户PK作为员工中与用户有FK关系(我猜是一对一)的一个额外字段。并为用户添加一个独立的PK(另一个guid以尊重表的其余部分)。如果要保证员工中的新外键(指向用户的外键)如果是唯一的,则始终可以添加唯一索引
这样,您就可以保持结构不变,摆脱循环。您还可以修改迁移类。在我的例子中,迁移类是:
CreateTable(
"dbo.Spendings",
c => new
{
SpendingId = c.Int(nullable: false, identity: true),
CategoryGroupId = c.Int(nullable: false),
CategoryId = c.Int(nullable: false),
Sum = c.Single(nullable: false),
Date = c.DateTime(nullable: false),
Comment = c.String(),
UserId = c.String(),
LastUpdate = c.String(),
})
.PrimaryKey(t => t.SpendingId)
.ForeignKey("dbo.Categories", t => t.CategoryId, cascadeDelete: true)
.ForeignKey("dbo.CategoryGroups", t => t.CategoryGroupId, cascadeDelete: true)
.Index(t => t.CategoryGroupId)
.Index(t => t.CategoryId);
删除“cascadeDelete:true”后,更新数据库工作正常
或作为false
.ForeignKey("dbo.Categories", t => t.CategoryId, cascadeDelete: false)
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove();
}
将此代码添加到上下文中,只需更新即可:
正如其他答案所建议的,您不需要对删除执行任何操作
table.ForeignKey(name: "FK_Cities_Regions_RegionId",
column: x => x.RegionId,
principalTable: "Regions",
principalColumn: "RegionId",
onDelete: ReferentialAction.NoAction);
注意:请执行referentialition.NoAction
ononDelete
让我弄清楚,您是否在Employee and Users表中对PK使用相同的值?是的,正如我预期的那样,应该先有一个用户值,然后再在Employee中使用它。错误仅在初始化时出现。嗨,Charles。我无法操作用户或Roles
或UsersInRoles
因为成员资格提供程序将停止工作。我可以更改表中的某个位置吗?EF正在尝试修改这些表。错误来自EF尝试添加外键约束。请尝试添加[NotMapped]到每个aspnet_*类定义。这将允许您使用这些类,但EF不会尝试为它们创建表。注意:如果使用此重写方法,请记住调用base.OnModelCreating(modelBuilder)
太多,否则将不会设置其他约定默认值。对我来说,这会导致新的错误,例如EntityType'IdentityUserRole'没有定义键。请定义此EntityType的键。
如果您使用的是database first design怎么办?这个答案仍然适用吗?我想使用它吗?它会有什么负面影响?这是一个问题我有时使用的解决方案,但这是因为我很少希望任何东西级联删除-我发现这可能是危险的
table.ForeignKey(name: "FK_Cities_Regions_RegionId",
column: x => x.RegionId,
principalTable: "Regions",
principalColumn: "RegionId",
onDelete: ReferentialAction.NoAction);