C# : Entity Framework(.NET Fx 3.5)簡単なまとめの追加 リレーションシップの更新

例のごとくこのようなデータ構造になっているとします。

SQLのテーブル:

image

Entity Frameworkのモデル

image

ProjectテーブルとShipテーブルにはリレーションが設定されています。

リレーションシップの変更

リレーションの変更を行いたい場合があります。たとえば上の例だとProjectでは船の所属を管理し、Shipでは船を管理しているのですが、船の所属を変えたい場合、普通にSQLで考えるとShipテーブルのprojectIdを変更すればいいだけですが、.NET Fx 3.5のEntity Frameworkではかなりやっかいです。

Entity Frameworkのモデルではテーブル間じゃないオブジェクト間のリレーションは、オブジェクト指向的な解釈で解決されているので、かなりやっかいです。もうこの辺を詳細に見出すとEntity Frameworkがいかに宇宙飛行士用のFrameworkであるか実感できます。

愚痴はともかく実際のコードです。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.EntityClient;
 
namespace EfSample1
{
    class Program
    {
        static void Main(string[] args) {
            using (ImportEntities context = new ImportEntities()) {
                //現状の表示
                var ships = from s in context.Ship.Include("Project")
                            orderby s.id
                            select s;
                foreach (var s in ships) {
                    Console.WriteLine("id: {0}; Project: {1}; Ship: {2}", 
                        s.id, s.Project.projectName, s.shipName);
                }
 
                int shipId = 2;
                int projectId = 4;
                //リファレンスを変更したい子オブジェクト
                Ship ship2 = context.Ship.First(s => s.id == shipId);
                //リファレンスの変更先になる親オブジェクト
                Project project4 = context.Project.First(p => p.id == projectId);
                //リファレンス先を変更する
                ship2.ProjectReference.EntityKey = context.CreateEntityKey("Project", project4);
                //変更をDBに反映する
                context.SaveChanges();
                //更新後の表示
                Console.WriteLine("=============================================");
 
                var ships2 = from s in context.Ship.Include("Project")
                             orderby s.id
                             select s;
                foreach (var s in ships2) {
                    Console.WriteLine("id: {0}; Project: {1}; Ship: {2}", 
                        s.id, s.Project.projectName, s.shipName);
                }
 
                Console.Read();
            
            }
        }
    }
}

 

大事なのは25行目から31行目です。

まずリレーションを変更したいShipオブジェクト(ship2)とそれた新たにリレーションを持たせたいProjectオブジェクト(project4)をコンテキストから取得します。(25行から27行)

次に取得したShipオブジェクトのProjectへのリファレンスであるProjectReferrence(EntityReference<T>)のEntityKeyプロパティに、コンテキストのCreateEntityKeyメソッドでリレーション先のKeyを作り挿入します。(29行)

コンテキストの SaveChange メソッドで、この変更をデータベースに反映します。(31行)

コード自体はシンプルですが、SQLえいえいっとやることに比べるとかなり回りくどいというか、きわめてOOP的で、SQLでのデータ操作に慣れているとかなり直感的でないです。だいたい外部キーに指定しているいるフィールドの値を書き換えるだけなのに、何で直接変更できずにこうなるんだか、もう何が何だか。

さすがに .NET 4 では改良され、外部キー指定されているフィールドを(OOP的に)直接更新できる様なので、もう少し直感的に変更できるはずです。

参考:

One thought on “C# : Entity Framework(.NET Fx 3.5)簡単なまとめの追加 リレーションシップの更新”

コメントを残す