2013-10-15 5 views
29

私は、このエラー

サイクルまたは複数のカスケードパスを引き起こす可能性が「領域」テーブルの上に 「FK_dbo.Regions_dbo.Countries_CountryId」FOREIGN KEY制約の紹介を取得しています。 ON DELETE NO ACTIONまたはON UPDATE NO ACTIONを指定するか、他のFOREIGN KEY制約を変更してください。 制約を作成できませんでした。以前のエラーを参照してください。

これは私のデータベース設計が悪いのですか?私はカスケードなどをオフにすることをお読みになりましたが、ラグから問題が掃除されているかどうかはわかりません。

私は、EFが自分のドメインクラスを使ってテーブルを生成するようにしています(私は、この時点でデータアノテーションや流暢なマッピングを使用していません)。

 public class Country 
     { 
      public Country() 
      { 
       this.Stores = new List<Store>(); 
       this.Regions = new List<Region>(); 
       Id = GuidCombGenerator.GenerateComb(); 
      } 

      public Guid Id { get; private set; } 

      private string name; 

      public string Name 
      { 
       get { return name; } 
       set 
       { 
        name = value.Trim(); 
       } 
      } 

      private string code; 

      public string Code 
      { 
       get { return code; } 
       set 
       { 
        code = value.Trim(); 
       } 
      } 

      public virtual ICollection<Store> Stores { get; set; } 
      public virtual ICollection<Region> Regions { get; set; } 
     } 


      public class City 
     { 
      public City() 
      { 
       this.Stores = new List<Store>(); 
       Id = GuidCombGenerator.GenerateComb(); 
      } 

      public Guid Id { get; private set; } 

      private string name; 

      public string Name 
      { 
       get { return name; } 
       set 
       { 
        name = value.Trim(); 
       } 
      } 


      public Guid RegionId { get; set; } 
      public virtual Region Region { get; set; } 

      public virtual ICollection<Store> Stores { get; set; } 
     } 


      public class Region 
     { 
      public Region() 
      { 
       this.Cities = new List<City>(); 
       this.Stores = new List<Store>(); 


       Id = GuidCombGenerator.GenerateComb(); 
      } 

      public Guid Id { get; private set; } 


      private string state; 

      public string State 
      { 
       get { return state; } 
       set 
       { 
        state = value.Trim(); 
       } 
      } 


      public Guid CountryId { get; set; } 
      public virtual ICollection<City> Cities { get; set; } 
      public virtual Country Country { get; set; } 
      public virtual ICollection<Store> Stores { get; set; } 
     } 


    public class Store 
    { 
     public Store() 
     { 
      Id = GuidCombGenerator.GenerateComb(); 

      Users = new List<User>(); 
     } 

     public Guid Id { get; private set; } 

     public Guid CountryId { get; set; } 
     public Guid CityId { get; set; } 
     public Guid RegionId { get; set; } 
     public virtual City City { get; set; } 
     public virtual Country Country { get; set; } 
     public virtual Region Region { get; set; } 

     public virtual ICollection<User> Users { get; set; } 

    } 

店舗が原因である可能性がありますか?

+0

はあなたが私たちに関係するテーブルを表示することができ、どのような彼らの構造が最も重要である、と:どのようにそれらの間にFK制約が設定されていますか?そこで、地域と国の間にカスケード削除を設定したいので、国が削除された場合、その地域はすべて削除されますか?合理的に聞こえる - 問題は、なぜこれがサイクルを引き起こすのだろうか?カスケード削除の他のFK制約には、すでに存在しているものはありますか? –

+0

私はこれらの領域を表示するように更新しました。コードを最初に作成しているので、まだテーブルが生成されていません。 – chobo2

+0

残念ながら、あなたは私たちに 'Store'クラスを見せていません....そしてカスケード削除を定義するコードは見当たりません... –

答えて

54

すべての外部キーのプロパティ(CountryIdRegionIdCityId)がないNULL可能あるため、モデル内のすべての関係は必要です。必要とされる1対多数の関係のために、EFは慣例によりカスケード削除を可能にする。

CountryRegionStoreテーブルに複数の削除パスを持って、例えばあなたがCountryを削除すると関連Store sが(SQL Serverと許可されていません)には3種類のカスケードパスを介して削除することができます。

    >から
  • Country - >Store
  • Country - >Region - >Store
  • Country - > - >Store

あなたはどちらか(NULL可能外部キーGuid?で)オプションような関係のいくつかを定義することにより、流暢APIを使用したり、削除カスケード無効にすることにより、このような曖昧な削除パスを避けなければなりません。

またはCityを除くすべてのエンティティからStoresコレクション(および逆参照とFKプロパティ)を削除します。私には、Regions.Cities.Storesコレクションをナビゲートして、すべての店舗をCountryに見つけることができるので、これらのコレクションは冗長に見えます。

+0

店舗はCityとの関係しかないのですか? – chobo2

+0

@ chobo2:はい、私はそれで十分だろうと思います。 – Slauma

+12

+1情報;ああ、SQL Serverのこの制限は面倒です。多くの場合、2つのテーブル間に多対1の関係を実装するテーブルがあり、関係テーブルの両方のテーブルにnull値のない外部キーを持たせたい場合や、これらのテーブルは関係テーブルにカスケードされます。だから私は外来キーの1つをヌル可能にする非常に非理想的な解決策が残っていると思います。毎回カスタムトリガーを実装するか、実装します。何ピタ。 – Shavais

24

次のようにあなたのDataContextファイルのOnModelCreating方法でmodelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>()を追加します。

public class YourDataContext : DbContext 
{ 
    public DbSet<Country> Countries{ get; set; } 
    ... 


    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>(); 

    } 
} 

同じ質問:entity-framework-how-to-solve-foreign-key-constraint-may-cause-cycles-or-multi

+18

これは解決策ではなく、問題を回避しています。 – Sebazzz

+4

これは、スキーマ設計を制御していない場合の正確な解決方法です。 – Askolein

+0

souluution səlo͞oSH(ə))n/ 名詞 1.難解な問題を解決する方法。 –