4

Page同様のページに関連付けられるクラスがあります。各関連付けには、関連付けに関する追加情報があります。これは、 の表現として定義されたクラスですPage

public class Page {
    [Key]
    public virtual int Id { get; protected set; }
    [Required]
    [StringLength(32)]
    public virtual string Name { get; set; }
    [InverseProperty("Page")]
    public virtual ICollection<Association> Associations { get; set; }
}

各ページは、任意の数の他のページと関連付けることができます。これは、ソース ページとターゲット ページとして定義されます。アソシエーションが一方向か双方向かは気にしません。どちらも私の特定のシナリオでは正当化されます (私は双方向のアソシエーションを好みますが、難しいです)。これがアソシエーション クラスです。

public class Association {
    [Key, Column(Order = 0)]
    public virtual int PageId { get; protected set; } // SOURCE
    [Required]
    public virtual Page Page { get; set; } // SOURCE
    [Key, Column(Order = 1)]
    public virtual int TargetId { get; protected set; } // TARGET
    [Required]
    public virtual Page Target { get; set; } // TARGET
    [Required]
    [StringLength(32)]
    public virtual string InformationAboutTheAssociation { get; set; }
}

今、私は次のコンテキストを持っています...

public class DbCtx : DbContext {
    public DbSet<Association> Associations { get; set; }
    public DbSet<Page> Pages { get; set; }
}

そして問題は、SQL Express が循環参照の可能性について不平を言っていることです (これは事実ではありませんが、過保護です)。説明されたシナリオを受け入れるために生成されたスキームをどのように解決しますか?

Introducing FOREIGN KEY constraint 'FK_dbo.Associations_dbo.Pages_TargetId' on table 'Associations' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.

ありがとう!

4

1 に答える 1

4

応答

エラーが示すことを実行します。 ON DELETE NO ACTION または ON UPDATE NO ACTION を指定します。同じエンティティへの 2 つの外部キーがあり、モデルが最初に (おそらく) 挿入されるon delete cascadeため、これを無効にする必要があります。ページが削除されると、関連付けは最初の外部キーによって削除されようとしますが、 2 番目の外部キー。

修正 3

public class DbCtx : DbContext {
public DbSet<Association> Associations { get; set; }
public DbSet<Page> Pages { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder) {
        modelBuilder.Entity<Association>()
            .HasRequired(x => x.Page)
            .WithMany(x => x.Associations)
            .WillCascadeOnDelete(false);
    }

}

これはうまくいくはずだと思います。

Page エンティティの削除

Page を削除しようとすると Associationを持っていないためon delete cascade、削除する Page エンティティに依存する Association エンティティがあると失敗します。

したがって、 Page を削除する場合は、まず Page を参照するすべての関連付けを削除する必要があります。関連からページへの外部制約 (実際には 2 つ) があります。それらの 1 つだけを使用し、一貫性を保ちます (ページまたはターゲットのいずれか)。

あなたがこの質問をしたので、あなたは SQL がどのように機能するかをよくわかっていないとしか言​​えません。そのため、データベースの設計と SQL の使用に関する本も読んだほうがよいでしょう。


EF で最初にコードを使用したことはありませんが、エンティティ関係図を考慮すると、Page には Association との「1 対多」があり、Association には Page との 2 つの「1 対 1」があります。

見た目が悪く、デザインが悪いので、これは周期的ではありませんか。

データベースを正規化します。

データベースを設計する場合 (最初にデータベース)、関連付けからページへの "1 対 1" (そのうちの 2 つ) の関係が既にあるため、ページと関連付けの間に "1 対多" の関係は必要ありません。そのため、pagId を知っている特定の関連付けを探したい場合は、select * from association where pageId or targetId = the id you are looking for.

最初にデータベースで EF を使用する場合、ページから関連付け (ここでやろうとしていること) への逆参照がありますが、データベース自体の実際のエンティティ関係モデルにはありません。それらは仮想参照です。

編集:

質問を読み直しましたが、問題は協会からページへの 2 番目の参照です。この場合、データベースは最初は正常に動作するため、奇妙です。

私はそれを徹底的に調べます。

于 2012-08-02T21:06:47.523 に答える