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
on
onDelete

让我弄清楚,您是否在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);