2017-09-25 7 views
2

EF CFカスケード削除を試す小さなデモソリューションを作成しようとしています。エンティティフレームワークコード最初にカスケードする1つを複数に削除

私が書いたコードでは、2台の車でPersonを追加しようとすると次のエラーが発生します。

2台の車を追加することを目的としています。その人を削除し、リンクされた車は同時に削除されます。

System.InvalidCastExceptionの:型のオブジェクトをキャストすることができません 'System.Collections.Generic.List`1は[EF_Cascading_Delete_Experiment.Car]' 'EF_Cascading_Delete_Experiment.Car' と入力します。私はここに車

のリストを持つ人がある簡単な例を構築しようとしています

は&カークラスの私人以下のとおりです。ここで

public class Person 
{ 
    [Key] 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public List<Car> Cars { get; set; } 
} 
public class Car 
{ 
    [Key] 
    public int id { get; set; } 
    public string CarName { get; set; } 
} 

をしようと私の単純なコードです2台付きの広告者:エラーが行で発生し

public static void CarTest() 
    { 
     using (Model1 db = new Model1()) 
     { 
      Person personToAdd = new Person(); 
      personToAdd.Name = "trev"; 
      personToAdd.Cars = new List<Car>(); 

      Car car1 = new Car 
      { 
       CarName = "Vectra" 
      }; 

      Car car2 = new Car 
      { 
       CarName = "Focus" 
      }; 

      personToAdd.Cars.Add(car1); 
      personToAdd.Cars.Add(car2); 

      db.Person.Add(personToAdd); 

      db.SaveChanges(); 
     } 
    } 

db.Person.Add(personToAdd); 

これは私のDbContextです:EFによって生成

public class Model1 : DbContext 
{ 
    // Your context has been configured to use a 'Model1' connection string from your application's 
    // configuration file (App.config or Web.config). By default, this connection string targets the 
    // 'EF_Cascading_Delete_Experiment.Model1' database on your LocalDb instance. 
    // 
    // If you wish to target a different database and/or database provider, modify the 'Model1' 
    // connection string in the application configuration file. 
    public Model1() 
     : base("name=Model1") 
    { 
    } 

    // Add a DbSet for each entity type that you want to include in your model. For more information 
    // on configuring and using a Code First model, see http://go.microsoft.com/fwlink/?LinkId=390109. 

    public virtual DbSet<Person> Person { get; set; } 
    public virtual DbSet<Car> Car { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<Person>() 
      .HasOptional(a => a.Cars) 
      .WithOptionalDependent() 
      .WillCascadeOnDelete(true); 
    } 
} 

移行コードは次のようになります。私には

public partial class addedbackeverythingincludingcascadingdelete : DbMigration 
{ 
    public override void Up() 
    { 
     CreateTable(
      "dbo.Cars", 
      c => new 
       { 
        id = c.Int(nullable: false, identity: true), 
        CarName = c.String(), 
       }) 
      .PrimaryKey(t => t.id); 

     CreateTable(
      "dbo.People", 
      c => new 
       { 
        Id = c.Int(nullable: false, identity: true), 
        Name = c.String(), 
        Cars_id = c.Int(), 
       }) 
      .PrimaryKey(t => t.Id) 
      .ForeignKey("dbo.Cars", t => t.Cars_id, cascadeDelete: true) 
      .Index(t => t.Cars_id); 

    } 

    public override void Down() 
    { 
     DropForeignKey("dbo.People", "Cars_id", "dbo.Cars"); 
     DropIndex("dbo.People", new[] { "Cars_id" }); 
     DropTable("dbo.People"); 
     DropTable("dbo.Cars"); 
    } 
} 

移行コードが正しくないように、それが見えますか?私のPerson & Carクラスに基づいて生成されたものです。しかし、私はなぜうまくいかないの?

データベースのテーブルを見ると、それらは間違っています。

enter image description here

確かに車のテーブルにPERSONIDがあるはず? PersonテーブルのCarIdではありませんか?

解決策:

これは私の解決策でした。私は答えを示すために彼の質問をマークすることができるようにここに置いた。

私のクラスでは、次のようになります。

public class Person 
{ 
    [Key] 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public virtual List<Car> Cars { get; set; } 
} 
public class Car 
{ 
    [Key] 
    public int id { get; set; } 
    public string CarName { get; set; } 
} 

すると、テスト、イワンが言うにもかかわらず、私はこのコードを保持しない限り、私は動作しないでしょうカスケードを削除見つかり、それを必要はありません

modelBuilder.Entity<Person>() 
      .HasMany(a => a.Cars) 
      .WithOptional() // or `WithRequired() in case Car requires Person 
      .WillCascadeOnDelete(true); 
+0

は、仮想キーワードで試してみてください。例:public virtual ICollection Cars {get;セット; } 'publicリストの代わりに' 車{get;セット; } ' –

+0

@AmitKumarと同じエラーです。 –

+0

1人で車がたくさんある場合、あなたの関係は間違って設定されます。車にはPerson_Id FKが必要です。あなたのリンクされたイメージを見てみましょう。(1対多カーの)関係ではなく、(多くの対1対1)関係を示します。 – Flater

答えて

4

流暢な関係の設定

modelBuilder.Entity<Person>() 
    .HasOptional(a => a.Cars) 
    .WithOptionalDependent() 
    .WillCascadeOnDelete(true); 

は間違っています。 HasOptional,HasRequired,WithOptionalDependent,WithOptionalPrincipalなどはone-to-oneの関係にありますが、one-to-manyの間は関係あります。次のように

正しい設定は次のとおりです。

modelBuilder.Entity<Person>() 
    .HasMany(a => a.Cars) 
    .WithOptional() // or `WithRequired() in case Car requires Person 
    .WillCascadeOnDelete(true); 

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

CreateTable(
    "dbo.People", 
    c => new 
     { 
      Id = c.Int(nullable: false, identity: true), 
      Name = c.String(), 
     }) 
    .PrimaryKey(t => t.Id); 

CreateTable(
    "dbo.Cars", 
    c => new 
     { 
      id = c.Int(nullable: false, identity: true), 
      CarName = c.String(), 
      Person_Id = c.Int(), 
     }) 
    .PrimaryKey(t => t.id) 
    .ForeignKey("dbo.People", t => t.Person_Id, cascadeDelete: true) 
    .Index(t => t.Person_Id); 
+0

私のクラスは正しいと思いますか? –

+0

- 人と車との関係を見ると、削除と更新のルールは "何もしない"と言われています –

+0

これは、コレクションのナビゲーションプロパティを持つone-to-manyを表す*有効な* EFモデルの1つです。 * one *側。また、多くの側で参照ナビゲーションやFKプロパティを追加することもできますが、必須ではありません*。 –

1

実際にあなたの車のモデルクラスにPersonプロパティを追加していません。 あなたのモデルはこのようにする必要があります。

ここをクリックCascade delete in one to many relationship

public class Person 
{ 
    [Key] 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public virtual ICollection<Car> Cars { get; set; } 
} 
public class Car 
{ 
    [Key] 
    public int id { get; set; } 
    public string CarName { get; set; } 
    public virtual Person Person { get; set;} 
} 

移行を実行します。そしてそれをテストしてください。

1

まず、私はそれが(遅延ロード用)Personクラスでvirtualキーワードを追加する方が良いと思う:

public virtual List<Car> Cars { get; set; } 

必要な注釈が付いている車クラスの人への参照を追加することができます

[Required] 
public virtual Person Person { get; set; } 

人が必要なので、人を削除すると、すべての車が削除されます。

関連する問題