2017-03-28 7 views
2

私は必要なプロパティで次のクラスを持っており、カスケード削除によって依存するプロパティを削除する際に問題が発生しています。私がしようとすると、次のコードを使用して、それを削除するには、市内をロードする場合必須プロパティが、Entity Frameworkコアでカスケードされないのはなぜですか?

public class City 
{ 
    [Key] 
    public int Id {get; private set; } 

    [Required] 
    public ZipCode ZipCode { get; private set; } 
} 


public class ZipCode 
{ 
    [Key] 
    public int Id { get; private set; } 

    [Required] 
    public string Zip { get; private set; } 
} 

City toDelete = db.CitySet.Where(c => c.Id == myCityReference.Id).FirstOrDefault(); 
db.CitySet.Remove(toDelete); 
db.SaveChanges(); 

を私は、その内部例外Npgsql.PostgresException: 23503: Update or delete on table "..." violates foreign key constraint.あるMicrosoft.EntityFrameworkCore.DbUpdateExceptionは、取得します。私は上記のincludeステートメントを追加した場合

はしかし、それは次のようになります。

City toDelete = db.CitySet.Include(c => c.ZipCode) 
    .Where(c => c.Id == myCityReference.Id).FirstOrDefault(); 

はその後、削除が正常に都市と郵便番号の両方を削除します。ただし、EFCore docsによると、必要な関係は削除機能Cascadeに設定されます。なぜこれは起こっていないのですか?私はEntity Framework Core v1.1.1とNpgsql v3.2.2を使用しています。あなたのよう

migrationBuilder.CreateTable(
    name: "ZipCodes", 
    columns: table => new 
    { 
     Id = table.Column<int>(nullable: false) 
      .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), 
     Zip = table.Column<string>(nullable: false) 
    }, 
    constraints: table => 
    { 
     table.PrimaryKey("PK_ZipCodes", x => x.Id); 
    }); 

migrationBuilder.CreateTable(
    name: "Cities", 
    columns: table => new 
    { 
     Id = table.Column<int>(nullable: false) 
      .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), 
     ZipCodeId = table.Column<int>(nullable: false) 
    }, 
    constraints: table => 
    { 
     table.PrimaryKey("PK_Cities", x => x.Id); 
     table.ForeignKey(
      name: "FK_Cities_ZipCodes_ZipCodeId", 
      column: x => x.ZipCodeId, 
      principalTable: "ZipCodes", 
      principalColumn: "Id", 
      onDelete: ReferentialAction.Cascade); 
    }); 

migrationBuilder.CreateIndex(
    name: "IX_Cities_ZipCodeId", 
    table: "Cities", 
    column: "ZipCodeId"); 

(これは、SQL Serverのですが、いくつかの特定のID列の注釈を除いて、それが他のデータベース・タイプで同じでなければなりません)

:ここ

+0

'Required'属性はナビゲーションプロパティに影響しますか?他のエンティティと流暢な構成があればそれを表示できますか? –

+0

こんにちは@IvanStoev、それは良い質問ですが、 'Required'がナビゲーションプロパティに反映されるかどうかわかりません。他のエンティティには、郵便番号である文字列があります。 Fluent設定は現在ありません。 – ArKi

+0

まだそれを見て良いです。例えば、 'public City City {get;}のような逆のナビゲーションプロパティを含んでいますか?セット; } '。 FKには共有PKを使用していますか?どのエンティティがデータベースにFKを含んでいますか?あなたが投稿した場合は、私はテストEFコアのコンテキストにそれらをドロップして、移行が何を言うのか見てみることができます。 –

答えて

4

は、モデルから生成された移行ですFKはカスケード削除がオンになって作成されます。ただし、FK列はCityテーブルにあり、ZipCodeテーブルを参照しています。つまり、ZipCodeがプリンシパルであり、Cityが依存していることを意味します。したがって、ZipCodeを削除すると、Cityがカスケードされます。その逆もありません。

また、ZipCodeId列には一意制約/インデックスがありません。これは、EFコアがone-to-manyの関係(1つはZipCodeから多くはCity)と仮定しています。

あなたが反対方向にカスケードにそれをしたい場合は、次のような流暢な設定を使用してZipCodeテーブルでFK列を配置する必要があります。

modelBuilder.Entity<City>() 
    .HasOne(e => e.ZipCode) 
    .WithOne() 
    .HasForeignKey<ZipCode>("CityId") 
    .OnDelete(DeleteBehavior.Cascade); 

今の移行は次のようになります。

カスケードすなわち
migrationBuilder.CreateTable(
    name: "Cities", 
    columns: table => new 
    { 
     Id = table.Column<int>(nullable: false) 
      .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn) 
    }, 
    constraints: table => 
    { 
     table.PrimaryKey("PK_Cities", x => x.Id); 
    }); 

migrationBuilder.CreateTable(
    name: "ZipCodes", 
    columns: table => new 
    { 
     Id = table.Column<int>(nullable: false) 
      .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), 
     CityId = table.Column<int>(nullable: true), 
     Zip = table.Column<string>(nullable: false) 
    }, 
    constraints: table => 
    { 
     table.PrimaryKey("PK_ZipCodes", x => x.Id); 
     table.ForeignKey(
      name: "FK_ZipCodes_Cities_CityId", 
      column: x => x.CityId, 
      principalTable: "Cities", 
      principalColumn: "Id", 
      onDelete: ReferentialAction.Cascade); 
    }); 

migrationBuilder.CreateIndex(
    name: "IX_ZipCodes_CityId", 
    table: "ZipCodes", 
    column: "CityId", 
    unique: true); 

CityからZipCodeにあるとの関係は(一意のインデックスに注意してください)one-to-oneです。

ここでは、実際の意図が何であるかわかりません。しかし、確実にデータベースカスケードの削除は参照されたテーブルから参照テーブルへの方向性です。

関連する問題