例のごとくこのようなデータ構造になっているとします。
SQLのテーブル:
Entity Frameworkのモデル
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的に)直接更新できる様なので、もう少し直感的に変更できるはずです。
参考:
- リレーションシップの定義と管理 (Entity Framework) (.NET 4用のMSDNライブラリです。)
コメント
[…] This post was mentioned on Twitter by Tadahiro Ishisaka, MKinside. MKinside said: Reading: Entity Framework(.NET Fx 3.5)簡単なまとめの追加 リレーションシップの更新 https://opcdiary.net/?p=4372 […]