80
ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた- at ヒーロー島 秋の収穫祭 2013 2013/10/12 きよくらならみ

ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

Embed Size (px)

DESCRIPTION

2013/10/12 .NET 勉強会 / ヒーロー島 『ヒーロー島 秋の収穫祭 2013』の同名のセッションの資料です サンプルソースやフォローアップなどはこちら: http://d.hatena.ne.jp/kiyokura/20131014/p1

Citation preview

Page 1: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

ADO.NETとORMとMicro-ORM

-dapper dot netを使ってみた-

at

ヒーロー島 秋の収穫祭 2013

2013/10/12

きよくらならみ

Page 2: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

自己紹介

• きよくら ならみ

– @kiyokura / id:kiyokura

• 岡山生まれ岡山育ちのプログラマー

– 現在は県内の某製造業で社内SE

• NET系の開発やWebアプリ開発

– Microsoft MVP for ASP.NET/IIS

Page 3: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

本セッションの目的

• Micro-ORMを知ってもらう

• dapper dot netを知ってもらう

Page 4: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

本セッションのゴール

• .NET向けのDBアクセス手法の概要を知る

• ORMの概要と"不得手"な部分を知る

• dapper dot netの概要を知る

Page 5: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

本日のアジェンダ

• .NETのDBアクセステクノロジの基本

• ORM 超・概要と.NETのORM

• ORM≠銀の弾丸

• Micro-ORM そしてdapper dot net

• まとめ

Page 6: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

.NETのDBアクセステクノロジの基本

Page 7: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

基本はADO.NET

• .NETにおけるDBアクセスの基本

• 様々なデータソースに対して『一貫性を持ったアクセス機能を実現』

Page 8: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

ADO.NET

ADO.NETのスタック

データソース(DBほか、xmlやExcel等)

データプロバイダ

Connection Command

DataReader

Transaction

Transaction DataAdapter

プログラム(C# or VB.NET or etc)

DataSet

DataTable

Page 9: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

一貫性のある操作

• 各ソースに対応した”プロバイダ”

– 製品専用のプロバイダ

• SQL Server

• SQL Server CE

• Oracle

• MySQL

• PostgreSQL

…等々。

– 汎用ドライバ用

• OLE DB

• ODBC

Page 10: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

プロバイダはインタフェースを実装

• 共通のインタフェースを実装することで操作の一貫性を保証

– IDataReader

– IDbConnection

– IDbCommand

– IDataParameter

– IDbTransaction

– IDbDataAdapter

Page 11: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

接続の基本:Connection

• Connectionオブジェクトに接続文字列をセット

• 接続を開始

Page 12: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

クエリ実行の基本:Command

• Commandオブジェクトによりクエリ実行

– DML・DDL・DCL

• CommandにSQLをセットして実行

• 結果としてレコードが返るときは?→ DataReaderを使う

Page 13: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

データ読込の基本:DataReader

• Commandの結果DataReaderが返る

• レコードに対して順番にアクセス

– DBのカーソルやADOのRecordSetに近い

Page 14: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

最も基本的なデータアクセス流れ

• DBに接続

– Connectionオブジェクト

• コマンドにSQLをセット

– Commandオブジェクト

• コマンドを実行してリーダーを作成

– DataReaderオブジェクト

リーダーをループしながらデータを読む

Page 15: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

最も基本的なデータアクセス流れ

DB

Connection

接続文字列(1)

Command

SQL: SELECT * FROM HOGEHOGE(2)

DataReader(3)

Page 16: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

コード例

Page 17: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

ここまでのまとめ

.NETのDBアクセスの基本はADO.NET

ソース毎に異なるプロバイダを利用

共通のインタフェースによりソースが変わっても一貫した操作を提供

データ読み込みの基本手順

Connectionで接続

Commandで実行

DataReaderで読込

Page 18: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

ORM 超・概要と.NETのORM

Page 19: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

ORMって?

• Object-Relational mapper / mapping

– O/RM 、 O/R-M、OR-M

– 「おーあーるまっぱー」

• 永続化データに対するギャップを埋める

– メモリ上の変数とDB上のカラムのマッピング

– "オブジェクト操作"と"DBの操作"

• その他、DB操作をラップ

Page 20: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

代表的な機能

• クエリの自動生成

• データ(値)のマッピング

• DB操作のラッピング

• ソースコード自動生成

ライブラリや実装よって有無はあります

Page 21: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

例:Entity Framework

• .NET用のORMであるEntity Frameworkを例としてデモします

– ASP.NET MVC 4 + Entity Framework

Page 22: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

Entity Frameworkの例

• メソッドを呼ぶだけでデータを取得

– 列挙型のオブジェクトとしてデータが「マネージドのオブジェクト」として取得できる

• オブジェクトに値とセットしてメソッドを呼べば更新完了

SQLを全く意識しない

DBの接続等の制御用もまったく意識しない

Page 23: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

.NETで利用できるORMの例

• マイクロソフト製

– ADO.NET DataSet

– LINQ to SQL

– Entity Framework

• サードパーティー製

– NHibernate

– S2Dao.NET

– LightSpeed(商用)

…等々

Page 24: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

ここまでのまとめ

ORMはDB操作をラップ

SQL作成や実行、データのオブジェクトへのマップ等

.NET向けにも多数の実装あり

Page 25: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

ORM≠銀の弾丸

Page 26: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

ORMを使うべきか否か

• "便利なケース"では使うべき

– どんどん使いましょう

• "美味しくない場合"は使わなくてよい

– 無理して使うようなものでもない

Page 27: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

ただし当然ですが

• 銀の弾丸は無い

• あらゆるケースで全く問題が無いわけでは無い

"美味しくない"例をいくつか考えてみます

Page 28: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

DB設計がORM適さなくなりがちなケース

• データがアプリケーション内に閉じない

– データが多数のアプリで横断的に利用される

– アプリから見えない業務ロジックが存在

• 『データ > アプリ』

– 利用範囲の他、権限や寿命

• データ中心アプローチ(DOA)

Page 29: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

基幹業務システムの例

販売データ

労務データ

製造データ

研究開発データ

顧客データ

販売管理システム 生産管理システム

賞与計算システム 製造品質管理システム

Page 30: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

パフォーマンスで問題が出るケース

• ORMでパフォーマンスが出ない場合が

– 仮に設計に問題がなくても

• パフォーマンス比較の例

手法 実行時間(短=速)

Hand coded(DataReaderでループ) 47ms

NHibernate SQL 104ms

Linq 2 SQL ExecuteQuery 181ms

Entity framework ExecuteStoreQuery 631ms

dapper dot net の公式サイト上のベンチマーク結果より( https://code.google.com/p/dapper-dot-net/ )

Page 31: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

その他のアリがちな話

• そもそもDB設計がイケてない

– 自動生成のクエリではパフォーマンスが(

– 適切にリレーションが貼られていない

• プロバイダが(使いたい)ORMに未対応

– たまにある

• DBサーバ・ネイティブクライアント・プロバイダのそれぞれのバージョンの対応とかも関連

• 自動生成されたSQLがDBAの怒りに触れる(

– DBA:「そんなトン○キなクエリ投げるな!」

Page 32: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

ここまでのまとめ

ORMのメリットが生きる場合は使うべき

ORMのメリットが生きない・使いにくい場面は存在する

そんなときは無理して使う必要はない

Page 33: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

Micro-ORMそしてdapper dot net

Page 34: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

ORMが使えなくても

• なるべく楽はしたい

• 生ADO.NETはいろいろ面倒

– Connectionはまだしも

– SQL組み立てて

– Commandを作って

– Parameterを作って

– 実行して

– 値をオブジェクトにマッピング

Page 35: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

そこでMicro-ORM

• 隙間を埋めてくれるソリューション

Page 36: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

Micro-ORMとは

• 特徴

– フルスタックのORMほどの機能は無いが

– そこそこ便利な機能があって

– 軽量で

– 早い

• そういうカテゴリ(?)のライブラリの総称

Page 37: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

機能のあるやなしや

クエリの自動生成

データ(値)のマッピング

DB操作のラッピング

ソースコード自動生成

☆物によってはある程度するものも

Page 38: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

つまり

• SQLは自分で書く必要がある

• 実行時の面倒なことのうち、ある程度のことをやってくれる

Page 39: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

代表例

• dappar dot net

– この後、少し詳しく話します

• Massive

– https://github.com/robconery/massive

• PetaPoco

– http://www.toptensoftware.com/petapoco

Page 40: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

dapper dot net

• Dapper.NETとも書かれる

– .NET向けのMicro-ORM

• オープンソース

– ApachとMITのデュアルライセンス

• サイトはこの辺

– https://code.google.com/p/dapper-dot-net

– https://github.com/SamSaffron/dapper-dot-net

Page 41: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

dapper dot net

• 作った人: Sam Saffron

– Stack Overflowの中の人

• 早い

– 生SQL実行(DataReader)とほぼ互角

– Stack Overflowのパフォーマンス改善のために作られた(らしい)

Page 42: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

dapper dot net

• どのDBで使える?

– ADO.NET準拠のプロバイダが使えるなら大抵いけるんでは?

• IDbConnectionの実装なら、多分

• 確認した範囲

– SQL Server / SQL Server CE

– Oracle

– MySQL

– postgreSQL

Page 43: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

使い方

• 2STEPで簡単!

Page 44: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

STEP1

• NuGetで一発導入!

Page 45: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

STEP2

• 使いたい場面でDapper名前空間をインポート

– 拡張メソッドなのでインポート必須!

Page 46: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

これだけです

Page 47: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

実際の例をご紹介します

• ADO.NETで直接実行する場合との対比で紹介します

Page 48: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

例1:とりあえずループして読みだす

Page 49: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

ADO.NETの場合

using (var cn = new SqlCeConnection(connectionString)){

cn.Open();

var sql = "select ID, Name , Age , Email From Employee;";var cmd = new SqlCeCommand(sql, cn);using (var dr = cmd.ExecuteReader()){

while (dr.Read()){

Console.WriteLine("ID:{0} , Name:{1} , Age:{2} , Email:{3}",dr["ID"],dr["Name"],dr["Age"],dr["Email"]);

}}

}

Page 50: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

dapperの場合

using (var cn = new SqlCeConnection(connectionString)){

cn.Open();

var sql = "select ID, Name , Age , Email From Employee;";var result = cn.Query(sql);foreach (var d in result){

Console.WriteLine("ID:{0} , Name:{1} , Age:{2} , Email:{3}",d.ID,d.Name,d.Age,d.Email);

}}

Page 51: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

ポイント1

• Query拡張メソッド

– Connectionオブジェクトを拡張

Page 52: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

ポイント2

• 戻り値はIEnumerable<dynamic>

Page 53: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

つまり

• Query拡張メソッドを実行すると

• 戻り値はIEnumerable<dynamic>が返ってくる

• dynamicの中身はカラム名から自動生成された匿名型にマップされている

Page 54: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

例2:用意した型にマップする

Page 55: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

ADO.NETの場合

using (var cn = new SqlCeConnection(connectionString)){

cn.Open();var cmd = new SqlCeCommand("select ID, Name , Age , Email From Employee;", cn);var result = new List<EmployeeEntity>();using (var dr = cmd.ExecuteReader()){

while (dr.Read()){

result.Add(new EmployeeEntity(){

ID = (int)dr["ID"],Name = (string)dr["Name"],Age = (int)dr["Age"],Email = (string)dr["Email"]

});}

}

foreach (var d in result){

Console.WriteLine("ID:{0} , Name:{1} , Age:{2} , Email:{3}",d.ID,d.Name,d.Age,d.Email);

}}

Page 56: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

dapperの場合

using (var cn = new SqlCeConnection(connectionString)){

cn.Open();var sql = "select ID, Name , Age , Email From Employee;";var result = cn.Query<EmployeeEntity>(sql);

foreach (var d in result){

Console.WriteLine("ID:{0} , Name:{1} , Age:{2} , Email:{3}",d.ID,d.Name,d.Age,d.Email);

}}

Page 57: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

ポイント1

• Query<T>拡張メソッド

– マップしたい型を型パラメータに指定

Page 58: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

ポイント2

• 戻り値はIEnumerable<dynamic>

Page 59: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

つまり

• 型パラメータTをとるQuery拡張メソッドを実行すると

• 戻り値はIEnumerable<T>が返ってくる

– クエリの結果が型Tにマップされている

• カラム名に対応したメンバにマップ

• 適切に型の変換も行われている

Page 60: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

例3:パラメータをバインドする

Page 61: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

ADO.NETの場合

using (var cn = new SqlCeConnection(connectionString)){

cn.Open();var cmd = new SqlCeCommand("select ID, Name , Age , Email From Employee where Age = @age;", cn);

var param = cmd.CreateParameter();param.SqlDbType = System.Data.SqlDbType.Int;param.Direction = System.Data.ParameterDirection.Input;param.ParameterName = "age";param.Value = 25;cmd.Parameters.Add(param);

var result = new List<EmployeeEntity>();using (var dr = cmd.ExecuteReader()){

while (dr.Read()){

result.Add(new EmployeeEntity(){

ID = (int)dr["ID"],Name = (string)dr["Name"],Age = (int)dr["Age"],Email = (string)dr["Email"]

});}

}foreach (var d in result){

Console.WriteLine("ID:{0} , Name:{1} , Age:{2} , Email:{3}",d.ID,d.Name,d.Age,d.Email);

}

Page 62: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

dapperの場合

using (var cn = new SqlCeConnection(connectionString)){

cn.Open();var sql = "select ID, Name , Age , Email From Employee where Age = @Age;";var result = cn.Query<EmployeeEntity>(sql, new { Age = 25 });

foreach (var d in result){

Console.WriteLine("ID:{0} , Name:{1} , Age:{2} , Email:{3}",d.ID,d.Name,d.Age,d.Email);

}}

Page 63: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

ポイント

• Query<T>拡張メソッドの第二引数にパラメータを指定

– SQL文のパラメータと同じメンバがあればOK

• 匿名型でもOK

Page 64: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

つまり

• Query拡張メソッドの第二引数に

• SQL文中のパラメータと同名のメンバを持つオブジェクトを渡すと

• パラメータとしてバインドして実行する

Page 65: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

その他

• 複数の型(ネストされた型)にバインドすることも可能

– 但し、基本1:1

• もちろん、INSERT / UPDATE / DELETE等も発行できる

Page 66: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

FAQ

Page 67: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

Q1:速度は?

• A1:早いです

– 生ADO.NETとほぼ誤差の範囲くらい

– 公式サイトのベンチマークも参照

Page 68: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

Q2: DB側の命名がsnake_case…

• A2-1:SQLで別名を付ける

– first_name as FirstName

• A2-2:SetTypeMapという仕組みを使う

– 詳細は公式サンプルや、neue ccさんのblogエントリを参照

• http://neue.cc/2012/12/11_390.html

Page 69: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

Q3:SQL書けません!

• A3:頑張って書いてください

– どうしても解らない人は、クエリビルダ的なツール使うといいのでは

• SQL Server Management Studio

• A5:SQL Mk-2

• SI Object Browser

– もしくは、ヘルパライブラリを使う手も

• Dapper.Rainbow

• Dapper.Contrib

Page 70: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

Q4:マップするクラスは自分書く?

• A4:自分で書きましょう

– 別途、自動化・半自動化はできるのでは

• DDLやDB定義書から

• マクロやT4で自動生成等

Page 71: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

補足情報

• ソースは1ファイルなのでGithubからとってきて入れてもいいです

– ちょっと改変して使いたいならそれが楽

• MySQLで高負荷かけると不具合が出るらしい

– 詳細と対策などはneue ccさんのblogエントリ参照:

• http://neue.cc/2013/08/06_423.html

Page 72: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

ここまでのまとめ

生ADO.NETとORMの間を埋める、Micro-ORM

dapper dot netは早くて手軽で便利

Page 73: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

まとめ

Page 74: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

まとめ(1)

• .NETのデータアクセスはADO.NETが基本

• ORMは便利だが使いにくいケースもある

• 間を埋める選択してのMicro-ORM

Page 75: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

まとめ(2)

• Micro-ORMは大体こんなもの

– SQLは自力で書く

– 実行結果やパラメータをマップしてくれる

• dapper dot net

– 多分もっともメジャーなMicro-ORM

– 手軽で便利、(割と)かゆいところに手が届く

Page 76: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

最後に

• 「ORMが適用しにくい」と思ったら無理に適用しなくていいです

– 無理に使っても余計な苦労を背負い込む事が多い気がします

Page 77: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

最後に

• 生ADO.NETよりも「もう少し文化的にやりたい」とき、dapperはお勧めのソリューションだと思います

• Web Pages(WeMatrix)にも良いかも

– WebMatrix.Dataに物足りなくなったときの次の一手として

Page 78: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

参考

Page 79: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

dapper公式関連

• 公式サイト

– https://code.google.com/p/dapper-dot-net/

• ベンチマーク結果あり

• ソースコード

– https://github.com/SamSaffron/dapper-dot-net

• テストコード(サンプルとしても有用)あり

– https://github.com/SamSaffron/dapper-dot-net/blob/master/Tests/Tests.cs

• Test内に、ベンチマークのプログラムもあり

Page 80: ADO.NETとORMとMicro-ORM -dapper dot netを使ってみた

その他

• Micro ORMs with Sam Saffron and Rob Conery

– http://www.infoq.com/articles/ORM-Saffron-Conery

– MassiveのRob ConeryとdapperのSam SaffronへのMicro-ORMについてのインタビュー記事