2015年11月04日

EntityFramework(14):リレーションのあるエンティティの削除

  
今回は、エンティティの削除について。

注文を削除する場合に、前回の最後のサンプルで示したAddメソッドを使った挿入と同じ感覚で、Removeメソッドを使うとどうなるでしょうか?

 // まずは、確認用に挿入
 using (var db = new NorthwindContext()) {
     Category cat = new Category { CategoryName = "New Category" };
     Product product = new Product { ProductName = "New Product", Category = cat };
     db.Products.Add(product);
     db.SaveChanges();                
 }

 // Removeメソッド呼び出し。
 using (var db = new NorthwindContext()) {
     var p = db.Products.First(x => x.ProductName == "New Product");
     var c = db.Categories.First(x => x.CategoryName == "New Category");
     c.Products.Remove(p);
     db.SaveChanges();
 }

 // Removeメソッドの結果確認
 using (var db = new NorthwindContext()) {
     var p = db.Products.First(x => x.ProductName == "New Product");
     var c = db.Categories.First(x => x.CategoryName == "New Category");
     var s1 = $"{p.ProductID} | {p.ProductName} | {p.CategoryID}";
     Console.WriteLine(s1);
     var s2 = $"{c.CategoryID} | {c.CategoryName}";
     Console.WriteLine(s2);
 }

結果は、

78 | New Product |
9 | New Category

となります。
1行目の最後のCategoryIDの値が表示されていません。
デバッグで中身を確認してみると、null になっています。
つまり、上のコードでは、関連が外れているだけで、テーブルからレコードが削除されているわけではないということです。

ProductのCategoryIDカラムが、null を許容しているからこういった状況が生まれます。

実際に、テーブルから該当するオブジェくトを削除するには、以下のようなコードを書く必要があります。

 using (var db = new NorthwindContext()) {
     var p = db.Products.First(x => x.ProductName == "New Product");
     var c = db.Categories.First(x => x.CategoryName == "New Category");
     c.Products.Remove(p);   // ★
     db.Categories.Remove(c);
     db.SaveChanges();
 }

★印の行はこのケースでは無くてもかまいません。
ProductのCategoryIDカラムが、null を許容していない場合は、★の行が必要です。
Productそのものもテーブルから削除し、そのあとに、Categoryテーブルから、該当する行を削除しています。

-----
あまりないシチュエーションだと思いますが、リレーションの変更もオブジェクト指向的なコードで実現できます。 ここでは、顧客間で注文を移動するコードを書いてみました。

 int orderID;
 using (var db = new NorthwindContext()) {
     Customer cust1 = db.Customers.Single(c => c.CustomerID == "ALFKI");
     Customer cust2 = db.Customers.Single(c => c.CustomerID == "FOLKO");
     // 最後の注文を取り出します。
     Order o = cust1.Orders.Last();
     orderID = o.OrderID;
     Console.WriteLine($"{o.OrderID}, {o.CustomerID}");
     // 顧客1から注文を削除し、その注文を別の顧客2に追加します。
     cust1.Orders.Remove(o);
     cust2.Orders.Add(o);
     db.SaveChanges();
 }
 // 移動できているかを確認
 using (var db = new NorthwindContext()) {
     var o= db.Orders.First(x => x.OrderID == orderID);
     Console.WriteLine($"{o.OrderID}, {o.CustomerID}");
 }

以下、結果です。確かに移動できました。

11011, ALFKI
11011, FOLKO



この記事へのコメント
はじめまして。検索をたどってきました。

リレーションのあるエンティティの削除 についてお教えいただきたい事があるのですがよろしいでしょうか。(ソースも貼るので数コメント分あります)
Posted by 雷持 at 2015年11月12日 14:58
雷持さん、当ブログにご訪問いただきありがとうございます。

このような質問が時々私のところに来ますが、原則として、お受けしないことにしています。そうしないと際限なくなってしまうので....
ご理解をお願いします。

MSDNフォーラム等のQ&Aサイトのご利用をお勧めします。

http://social.msdn.microsoft.com/Forums/ja-jp/home

なお、記事に対して「コードが間違ってるよ」とか「うまく動かないけど..」とか「こんな書き方もあるよ」「僕はこう書いてるけど、どう思う?」といったコメントは大歓迎です。

Posted by Gushwell at 2015年11月12日 20:14
返信をありがとうございます。失礼いたしました。
Posted by 雷持 at 2015年11月12日 20:40
 

この記事へのトラックバックURL

http://trackback.blogsys.jp/livedoor/gushwell/52439481