よろしい、ならばmicro-ormだ
DESCRIPTION
第二回 中国地方DB勉強会の同名のセッションの資料です。TRANSCRIPT
よろしい、ならばMicro-ORMだ
きよくら ならみ
第二回 中国地方DB勉強会
2013/10/05
自己紹介
• きよくら ならみ
– @kiyokura / id:kiyokura
• 岡山生まれ岡山育ちのプログラマー
–現在は県内の某製造業で社内SE
• NET系の開発やWebアプリ開発
– Microsoft MVP for ASP.NET/IIS
ORMとSQLと
ORM派 vs SQL派(?)
• よく論争になってる(?)
• でも今日はそんな話はしません
• (そもそも個人的には対立軸ではないと思ってます)
先に私の個人的結論を言うと
• ORM使えばいい
• むしろどんどん使うべき
ただし銀の弾丸じゃない
• コンテキスト次第
–「デメリットが勝つ」というべきか、「メリットが有効に働かない」というべきか
–そういうことはある
でも面倒なのは避けたいです
• ORMが使えなくても
–なるべくならば
今日のお話の流れ
• ORMについて
• ORMがあんまり有効でないケース
• Micro-ORMについて
ORMとは
ORMの代表的な機能
• クエリの自動生成
• データ(値)のマッピング
• DB操作のラッピング
• ソースコード自動生成
• もちろん実装によっては無い機能もある
"面倒くさい"ところを便利に
• SQL
• エンティティになるクラス
• DB操作をいちいち書かなくていい
• 単体テストが必要な個所が削れる
• 実装によって異なる場合があります
便利なのでどんどん使えばいいよ
• そう思います
ORMが有効じゃないケースとは
ORMが有効でないケースもある
• 往々にして"銀の弾丸"は無いです
• 幾つかあると思いますが、もっとも根本的なお話をしたいと思います
DB設計がORMに適さないケース
• 例えばデータが単一のアプリケーション内に閉じないケース
こんな感じとか
販売データ
労務データ
製造データ
研究開発データ
顧客データ
販売管理システム 生産管理システム
賞与計算システム 製造品質管理システム
データベース ">" アプリケーション
• 何が「>」?– 利用範囲や権限、寿命等
• データが横断的に利用される– 例えば基幹系システムでは良くありますよね
• キーワード:データ中心アプローチ(DOA)
その他ORMが使いにくいと思われるケース
• DB設計がイケてない!
–パフォーマンスが出ない
–適切にリレーションが貼られていない
–もちろん私にそれを変更する権限は(
• ドライバ・プロバイダが使いたいORMに対応してない
–たまにある
ORMが使えないならどうするか
• もちろん、使わずに書くしかない
• SQL組み立てて...
• DBの接続情報を読み込んで...
• DBに接続して...
• おっと、例外時の処理もしっかりしとかないと
• パラメータをバインドして…
• クエリを実行!
そして…
• レコードの値を変数にセット、• レコードの値を変数にセット、• レコードの値を変数にセット、• レコードの値を変数にセット、• レコードの値を変数にセット、• レコードの値を変数にセット、• レコードの値を変数にセット、• レコードの値を変数にセット、• レコードの値を変数にセット、• レコードの値を変数にセット
決まりきったことは書きたくない
• 生産効率云々...
• Lazinessはプログラマの三大美徳の一つ
• どうにかズル出来ないものか
真面目な話、
• 自力でコードを書く量が少ないに越したことはない
–仮に実装にかかる時間が同じとしても
–バグを積み込む可能性は減る
• テストするべき個所が減る
そこで、今日の本題です
Micro-ORMってなに??
大体こんなもの
• 軽量で
• 高速な
• プチORM…とでも言うもの
"プチ”故に...
クエリの自動生成
データ(値)のマッピング
DB操作のラッピング
ソースコード自動生成
☆物によってはある程度するものも
このあたりを面倒見てくれる
• DB操作のラッピング
–クエリ実行は面倒見てくれる
–接続やトランザクション制御は"ある程度"は自動でやってくれる
• 値のマッピング
–クエリの結果セットの取得とマッピング
–クエリのパラメータへのマッピング
軽量で早い
• ソースコード1~2ファイルとかの実装が多い
• あんまり複雑なことしない分早い
• クエリの実行速度は"あなたが組んだSQLに依存する"
Micro-ORMの実装例の紹介
実装例
• 代表的な実装例
– dappar dot net
– Massive
– PetaPoco
• あれ?なんか.NETの実装ばっかりだ:p
• dapper dot netを例に少しだけ紹介
おことわり
• .NETの実装ですのでコードも.NETです
• 今日はざっくりとさらっと
• 詳しいコード例やデモ、他のORMとの比較などは…
来週(10/12)のヒーロー島で!
• 「ヒーロー島 秋の収穫祭 2013」
• こちらでは、よりコード例や機能の紹介などを行いたいと思います
• 10/12(日)、八丁堀のMS中四国支店– 八丁堀電停から徒歩3分
• 詳細とお申し込みはこちら– http://heroshima.jp/EventInfo/autumn2013
dapper dot net
• .NET向けのMicro-ORM
– Dapper.NETとも書かれる
• オープンソース
– ApachとMITのデュアルライセンス
• サイトはこの辺
– https://code.google.com/p/dapper-dot-net/
– https://github.com/SamSaffron/dapper-dot-net
dapper dot net
• 対象データベース
–たいがい行ける気がします
• ADO.NETに準拠したプロバイダがあれば
• SQL Server / Oracle / MySQL / PostgreSQL
• 最悪ODBCあれば行ける気がする
導入は簡単
• NuGetで一発インストール
実際の使用例
• 実際にdapperを使った例をお見せします
...とその前に
• dapperやORMを使わずに書いたDBアクセスの例
public IList<EmployeeEntity> FindAll(){
using (var cn = new SqlCeConnection(connectionString)){
cn.Open();var sql = "select ID, Name , Age , Email From Employee;"var cmd = new SqlCeCommand(sql , 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"]
});}
}return result;
}}
var cmd = new SqlCeCommand(sql , 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"]
});}
}
①実行の下準備(コマンドオブジェクト作成)②実行して③型変換とかしながらクエリの結果をオブジェクトにマッピング
カラムが増えると
もっと面倒に!
dapperを使うとどうなるか
public IList<EmployeeEntity> FindAll(){
using (var cn = new SqlCeConnection(connectionString)){
cn.Open();var sql = "select ID, Name , Age , Email From Employee;"return cn.Query<EmployeeEntity>(sql).ToList();
}}
return cn.Query<EmployeeEntity>(sql).ToList();
この一行で、実行結果のマッピングまですべて完了!
ポイントはQuery拡張メソッド
• コネクションオブジェクトの拡張メソッドとして実装
• Query拡張メソッドの各種オーバーロード
デモ
もう一つ、例
• パラメータをバインドしてみます
こちらも非dapperから
public EmployeeEntity FindByID(int id){
using (var cn = new SqlCeConnection(connectionString)){
cn.Open();var sql = "select ID, Name , Age , Email From Employee where ID = @ID;"var cmd = new SqlCeCommand(sql, cn);
var param = cmd.CreateParameter();param.ParameterName = "ID";param.SqlDbType = System.Data.SqlDbType.Int;param.Direction = System.Data.ParameterDirection.Input;param.Value = id;cmd.Parameters.Add(param);
var result = new List<EmployeeEntity>();using (var dr = cmd.ExecuteReader()){
if (dr.Read()){
return new EmployeeEntity(){
ID = (int)dr["ID"],Name = (string)dr["Name"],Age = (int)dr["Age"],Email = (string)dr["Email"]
};}else{
return null;}
}}
}
var sql = "select ID, Name , Age , Email From Employee where ID = @ID;"
var cmd = new SqlCeCommand(sql, cn);
var param = cmd.CreateParameter();param.ParameterName = "ID";param.SqlDbType = System.Data.SqlDbType.Int;param.Direction = System.Data.ParameterDirection.Input;param.Value = id;cmd.Parameters.Add(param);
①Parameterオブジェクトを作成して②Parameterオブジェクトに値その他を設定③Commandオブジェクトにパラメータをセット
パラメータの数だけ、これをやらないといけない!!!
これがdapperだと…
public EmployeeEntity FindByID(int id){
using (var cn = new SqlCeConnection(connectionString)){
cn.Open();var sql = "select ID, Name , Age , Email From Employee where ID = @ID;"
return cn.Query<EmployeeEntity>( sql , new { ID = id }).SingleOrDefault();}
}
return cn.Query<EmployeeEntity>( sql , new { ID = id })
.SingleOrDefault();
Queryメソッドの第二引数に、
パラメータと名前の一致するプロパティを持ったオブジェクトを渡してやるだけ(匿名クラスでもOK)
パラメータが増えたら…new {
ID = id,Name = "ほげほげ",Age = 17
}
もっといろいろな機能があります
• 詳細は公式のGithub等にあるサンプルを見てみてください
–私もblogで書こうとしてるけど下書きだけ溜まっててまだ公開出来てません...
想定FAQ:1
• Q:実績あるの?
• A:結構いろいろあるらしい
– IT技術者的には「Stack Overflowで使われている」といえば納得できるかな?
–そもそも作者がStack Overflowの中の人
– Stack Overflowのパフォーマンス改善のために作られたらしい
想定FAQ:2
• Q:実際、パフォーマンスどうなの?
• A:相当早いよ
–詳しくは公式サイトにベンチマークあるので参照
想定FAQ:3
• Q:PHPで普通に書くのと一緒じゃね?
• A:静的型付けなのに同じってすごくね?
–コンパイラの恩恵
– IDEのサポート
• インテリセンス
• リアルタイムにコンパイルエラー
まとめ
ORMは便利な道具
• 有効に使えるところではどんどん使おう
• でも使えないケースもある
–設計思想やスケールのアンマッチ
–銀の弾丸は無い
Micro-ORMという選択肢
• 軽量高速、省力プログラミング
• ORMとSQLのいいところどりも可能
ご清聴ありがとうございました
and , Question?