ここ最近調べてたことだけど、やっと出来た!!
ということでVisual Studioを使ってみた感じだとSQL Serverにしか対応してないように見えるEntityFrameworkを、PostgreSQLで使うメモです。
(PostgreSQLはインストール済みの前提で話します)
試した環境は、Windows Vista Business SP1 + Visual Studio 2008 SP1 + PostgreSQL 8.3です。
Npgsqlのインストール
OSSのPostgreSQL用のDataProviderのNpgsqlをダウンロードします。
ここで使用したNpgsqlは2.0.4です。
pgFoundryの中からNpgsql2.0.4-bin-ms.net3.5.zipをダウンロードしました。
ダウンロードをしたら解凍して、適当な場所に置いておきます。
次に、Visual Studio 2008 コマンドプロンプトを管理者権限で実行して、Npgsqlを解凍したフォルダ(以下[NPGSQL_HOME])のbinに移動します。
gacutilを使ってNpgsql.dllとMono.Security.dllをGACへ登録します。
gacutil /i Npgsql.dll
gacutil /i Mono.Security.dll
そうすると、C:\Windows\assemblyに以下のように登録されます。
次に、C:\Windows\Microsoft.NET\Framework\v2.0.50727\CONFIG\machine.configにNpgsqlを登録します。
<configuration>
<!-- 省略 -->
</system.data>
<DbProviderFactories>
<!-- 省略 -->
<!-- ↓を追加する。Versionは、自分がGACに登録したNpgsql.dllのバージョンに揃えること -->
<add name="Npgsql Data Provider" invariant="Npgsql" description=".Net Framework Data Provider for Postgresql Server" type="Npgsql.NpgsqlFactory, Npgsql, Version=2.0.4.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7" />
</DbProviderFactories>
</system.data>
<!-- 省略 -->
</configuration>
ここら辺で、マシンを再起動しておくと、精神衛生上いいかもしれません。
DBの作成
テスト用のDBを作成します。
DB名はsampleで、ログインのためのIDとパスワードは共にpostgresという設定で書きます。
適時置き換えてください。
DBの作成
CREATE DATABASE sample
WITH OWNER = postgres
ENCODING = 'UTF8';
テーブルの作成
CREATE TABLE departments
(
id serial NOT NULL,
"name" character varying(50),
CONSTRAINT departments_pkey PRIMARY KEY (id)
)
WITH (OIDS=FALSE);
ALTER TABLE departments OWNER TO postgres;
CREATE TABLE employees
(
id serial NOT NULL,
"name" character varying(50),
dept_id integer,
CONSTRAINT employees_pkey PRIMARY KEY (id),
CONSTRAINT fk_employees_departments FOREIGN KEY (dept_id)
REFERENCES departments (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (OIDS=FALSE);
ALTER TABLE employees OWNER TO postgres;
テスト用データの投入
INSERT INTO departments(
"name")
VALUES ('人事部');
INSERT INTO employees(
"name", dept_id)
VALUES ('田中 太郎', 1), ('田中 次郎', 1);
これで、おなじみ?の従業員と部署のテーブルが出来上がります。
部署は人事部だけで、人事部に田中太郎さんと次郎さんが所属してるだけの単純なものです。
Npgsqlのインストールの確認
DBが出来たので、Npgsqlが正しくインストールされているか確認します。
ConsoleApplicationをNpgsqlTestという名前で作成します。
参照の追加で、NPGSQL_HOME\bin\Npgsql.dllを追加して、以下のプログラムをMainに書きます。
using System;
using System.Data.Common;
namespace NpgsqlTest
{
class Program
{
static void Main(string[] args)
{
// Npgsqlがきちんと登録されているか確認
var factory = DbProviderFactories.GetFactory("Npgsql");
// きちんと接続できるか確認
var conn = factory.CreateConnection();
conn.ConnectionString = "Server=localhost;Port=5432;User id=postgres;password=postgres;Database=sample;";
conn.Open();
// サンプルDBにSQL実行できるか確認
var command = conn.CreateCommand();
command.CommandText = @"
select
e.id as id, e.name as name, d.name as dept_name
from employees e
join departments d on e.dept_id = d.id";
var reader = command.ExecuteReader();
while (reader.Read())
{
Console.WriteLine("{0} {1} {2}",
reader["id"],
reader["name"],
reader["dept_name"]);
}
// まぁテストなのでネストが深くならないように手抜きClose
reader.Close();
conn.Close();
}
}
}
実行すると、以下のような結果が出力されるはずです。
1 田中 太郎 人事部
2 田中 次郎 人事部
続行するには何かキーを押してください . . .
ついにEntity Framework
下準備が完了したので、Entity Frameworkで、サンプルのデータベースに繋いでみようと思います。
ConsoleApplicationをNpgsqlEntityFWTestという名前で作成して、NPGSQL_HOME\Npgsql.dllを参照に追加します。
SQL Serverなら、ここからウィザードで…ということになるのですが、Npgsqlはコマンドラインからになります。
Visual Studio 2008 コマンドプロンプトを起動して、NpgsqlEntityFWTestプロジェクトのフォルダまで移動します。
edmgen.exeコマンドを使って、データベースから必要なファイル群を作成します。
今回のsampleデータベースにアクセスするものを作るのは、以下のようなコマンドになります。
edmgen.exe /provider:Npgsql /mode:fullgeneration /c:"Port=5432;Encoding=UTF-8;Server=localhost;Database=sample;UserId=postgres;Password=postgres" /project:SampleDB
正常に終了した場合は、以下のようなメッセージが表示されます。
Microsoft (R) EdmGen version 3.5.0.0
Copyright (C) 2008 Microsoft Corporation. All rights reserved.
データベースの情報を読み込んでいます...
ssdl ファイルを書き込んでいます...
格納層から概念層を作成しています...
msl ファイルを書き込んでいます...
csdl ファイルを書き込んでいます...
オブジェクト層ファイルを書き込んでいます...
ビュー ファイルを書き込んでいます...
生成完了 -- エラー 0 件、警告 0 件
以下の5ファイルが作成されます。
- SampleDB.csdl
- SampleDB.msl
- SampleDB.ObjectLayer.cs
- SampleDB.ssdl
- SampleDB.Views.cs
このファイルを全部プロジェクトに追加します。
この中のcsファイル以外は、ビルドアクションを「埋め込まれたリソース」に変更します。
ビルドすると、参照が足りないというエラーになるので、System.Data.EntityとSystem.Runtime.Serializationを参照に追加します。
ビルドエラーも消えたので、さくっとデータをとって表示するプログラムを書いてみます。
using System;
using System.Linq;
using SampleDB;
namespace NpgsqlEntityFWTest
{
class Program
{
static void Main(string[] args)
{
using (var ctx = new SampleDBContext())
{
// LINQ!!
var emps = from emp in ctx.employees
select new
{
ID = emp.id,
Name = emp.name,
DeptName = emp.departments.name
};
foreach (var emp in emps)
{
Console.WriteLine(emp);
}
}
}
}
}
この状態で実行すると、接続文字列が無いという例外が出てしまうので、App.configを追加して以下のように接続文字列を追加します。
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<!--
SampleDBという名前で作成した場合はSampleDBContextという名前で追加します
metadataの部分にres://*/csdlやmslやssdlの名前という形で|で区切って指定します。
後はProviderと接続文字列を指定します。
-->
<add name="SampleDBContext"
connectionString="metadata=res://*/NpgsqlEntityFWTest.SampleDB.csdl|res://*/NpgsqlEntityFWTest.SampleDB.msl|res://*/NpgsqlEntityFWTest.SampleDB.ssdl;provider=Npgsql;provider connection string="Server=localhost;Port=5432;UserID=postgres;Password=postgres;Database=sample""
providerName="System.Data.EntityClient"/>
</connectionStrings>
</configuration>
これで完成です。プログラムをコンパイルして実行すると以下のように表示されるはずです!
{ ID = 1, Name = 田中 太郎, DeptName = 人事部 }
{ ID = 2, Name = 田中 次郎, DeptName = 人事部 }
続行するには何かキーを押してください . . .
更新も、以下のような感じでいけます。
var updateTarget = ctx.employees.OrderBy(arg => arg.id).First();
updateTarget.name = "更新 太郎";
ctx.SaveChanges();
色々調べても、PostgreSQLでEntityFramework使うという、まとまった情報が無かったので書いてみました。
何か間違ってたりしたらコメント等で教えてくださいm(_ _)m