37

この問題についてはたくさんの質問がありますが、私は自分のケースを解決できませんでした。誰かがこれを見てください:

とテーブルとの関係が1対多のテーブルOfficeがあります。最後のテーブルは両方とも、によって作成された事前定義されたテーブルと共有主キーの関係を持つテーブルから派生しています。テーブルとテーブルの間には、私が手がけていない多くの関係があるようです。DoctorSecretaryEmployeeUserssqlmembershipproviderUsersRoles

Employee私の問題は、テーブルとそのテーブルの間に(zero、one)-(one)関係を作成することでしたUsers。これは、それらの間の共有主キー関係で終了し、エラーが発生しました。(その問題に対するより良い解決策はありますか?)

ここにエラーがあります:

テーブル'aspnet_UsersInRoles'にFOREIGNKEY制約'FK_dbo.aspnet_UsersInRoles_dbo.aspnet_Users_UserId'を導入すると、サイクルまたは複数のカスケードパスが発生する可能性があります。ON DELETENOACTIONまたはONUPDATENO ACTIONを指定するか、他のFOREIGNKEY制約を変更します。制約を作成できませんでした。以前のエラーを参照してください。

リバースエンジニアリング後の私のコードとメンバーシップコードは次のとおりです。

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; }
}

編集:Usersそして関係はより深くなり、テーブルとApplicationsテーブルの間、そしてまたの間にも多対一の関係がRolesありApplicationsます。

4

5 に答える 5

67

流暢なAPIを使用して、エラーメッセージが提案するアクションを指定できます。

あなたの文脈で:

protected override void OnModelCreating( DbModelBuilder modelBuilder )
{
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<aspnet_UsersInRoles>().HasMany(i => i.Users).WithRequired().WillCascadeOnDelete(false);
}

テーブルaspnet_UsersInRolesの定義が含まれていないため、このコードが機能しない可能性があることに注意してください。

別のオプションは、これを追加してすべてのCASCADEDELETESを削除することです

modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

流暢なAPIとの関係の構成についてさらに情報が必要な場合は、http://msdn.microsoft.com/en-US/data/jj591620をお勧めします

于 2013-01-24T03:44:47.207 に答える
21

また、移行クラスを変更することもできます。私の場合、移行クラスでは次のようになりました。

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)
于 2014-08-26T19:28:35.823 に答える
7
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
    }

このコードをコンテキストに追加します

于 2015-02-10T07:47:48.300 に答える
3

あなたのコメントに基づくと、問題は両方のテーブルで同じPKを使用していることです。私はすぐにそれを変更し、ユーザーとFKの関係を持つ従業員の追加フィールドとしてユーザーPKを使用します(私は1対1だと思います)。そして、独立したPKをユーザーに追加します(残りのテーブルを尊重するための別のGUID)。Employeesの新しい外部キー(Usersを指すキー)が一意であることを保証したい場合は、いつでも一意のインデックスを追加できます。

そうすれば、構造をすべて同じに保ち、サイクルを取り除くことができます。

于 2013-01-24T15:30:09.543 に答える
2

ただの更新

他の回答が示唆しているように、削除時にアクションを実行する必要はありません。これを行うための更新された方法は、EntityframeworkCore1.0では次のとおりです。

table.ForeignKey(name: "FK_Cities_Regions_RegionId",
                 column: x => x.RegionId,
                 principalTable: "Regions",
                 principalColumn: "RegionId",
                 onDelete: ReferentialAction.NoAction);

注:実行ReferentialAction.NoActionするonDelete

于 2017-09-19T18:00:04.523 に答える