LINQ to SQLを使ってみる
.NET3.5から追加されたLINQ、そのSQLアクセス用であるLINQ to SQLをさわってみた。
LINQ to SQLを使用する
を見てみると、今までのADO.NETとは違いO/Rマッピングフレームワークになっているのがよくわかる。
データベースの作成
「HogeService」という名前でデータベースを作り、テーブルは以下のように定義。
Customer
列名 | 型 | 備考 |
---|---|---|
ID | int | PK, NOT NULL, IDENTITY |
Name | varchar(50) | NOT NULL |
Product
列名 | 型 | 備考 |
---|---|---|
ID | int | PK, NOT NULL, IDENTITY |
Name | varchar(50) | NOT NULL |
CustomerID | int |
リレーション
Customer | Product |
---|---|
ID | CustomerID |
それぞれのテーブルに適当にデータを突っ込む。
Customer
ID | Name |
---|---|
1 | ジョン |
2 | ポール |
3 | シンディ |
4 | キャサリン |
5 | ドン |
Product
ID | Name | CustomerID |
---|---|---|
1 | テレビ | 5 |
2 | ビデオ | 4 |
3 | 時計 | 3 |
4 | iPod | 2 |
5 | ニップレス | 1 |
プロジェクトの作成
Visual Studio 2008 Beta2 を使用する。
まずは「ConsoleApplication」プロジェクトを作成する。プロジェクトに新しいアイテムとして「LINQ to SQL Classes」を追加する。ファイル名は「HogeService.dbml」とする。
「サーバーエクスプローラー」を開いて、先程作成したデータベースを追加する。そこから「Product」と「Customer」テーブルを「HogeService.dbml」のデザイナ上にDrag&Dropする。
これで列定義をプロパティとして持つ「Product」と「Customer」クラスが自動的に作られる。
いざLINQ
これでLINQ to SQLを使う準備ができたので、まずは「Product」のデータを全件検索してみる。
class Program { static void Main() { HogeServiceDataContext db = new HogeServiceDataContext(); var resultSet = from product in db.Products select product; foreach(var product in resultSet) { Console.WriteLine( "ID={0}, Name={1}, Customer={2}", product.ID, product.Name, product.Customer.Name ); } Console.Read(); } }
「HogeService.dbml」を作ると「HogeServiceDataContext」というクラスが作られる。
LINQ to SQLではこのクラスに対して各種CRUD操作を行う。
まずはこのクラスをインスタンス化する。ちなみにDBへの接続情報はアプリケーション構成ファイルに定義されている。「Product」テーブルに対して検索を行うので、「HogeServiceDataContext」の「Products」プロパティに対してLINQクエリを発行する。出力結果は以下。
ID=1, Name=テレビ, Customer=ドン
ID=2, Name=ビデオ, Customer=キャサリン
ID=3, Name=時計, Customer=シンディ
ID=4, Name=iPod, Customer=ポール
ID=5, Name=ニップレス, Customer=ジョン
驚いた事に「Product」テーブルと「Customer」テーブルがリレーションを張っている事で自動的に「Product」クラスには「Customer」型の「Customer」プロパティが作られている。すげー!!
次はちょっと検索条件を変えてみる。
class Program { static void Main() { HogeServiceDataContext db = new HogeServiceDataContext(); var resultSet = from product in db.Products where product.Name.Contains("ビ") orderby product.Customer.ID select product; foreach(var product in resultSet) { Console.WriteLine( "ID={0}, Name={1}, Customer={2}", product.ID, product.Name, product.Customer.Name ); } Console.Read(); } }
「Product」の「Name」プロパティに"ビ"を含むものを検索して、「Customer」の「ID」でソートする。
ID=2, Name=ビデオ, Customer=キャサリン
ID=1, Name=テレビ, Customer=ドン
すげー!!!!!!!!!!!!!
いままでDAOとかしこしこ作ってたけど、そういうのが全くいらなくなる。ここまで簡単に使えるとiBatis.NETとかNHibernateとかはもう使う気になれない。設定ファイルとか一切いらんもん。
- 設定ファイル(iBatis.NET、NHibernate)
- 属性ベース(
ActiveRecordなんかあるやろ) - コーディング規約(Ruby on Railsのやつ)
ちなみに
自動生成されたコードを見てみると
partial void OnCreated(); partial void InsertProduct(Product instance); partial void UpdateProduct(Product instance); partial void DeleteProduct(Product instance); partial void InsertCustomer(Customer instance); partial void UpdateCustomer(Customer instance); partial void DeleteCustomer(Customer instance);
というのがあった。
パーシャルメソッドで各CRUD操作時にユーザ定義の処理を埋め込めるようになっている。
今までならこの手のやつはクラスを継承して「On〜」というのをオーバーライドするかイベントにイベントハンドラを追加していたけど、これならいちいちクラスを継承しなくても、パーシャルクラスを作ればいいだけなのですごく便利。パーシャルメソッドの使い道がいまいち不明やったけど、これでわかった。