Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.

DeclarativeSql

5 574 vues

Publié le

2015/03/29

北陸新幹線開通記念!北陸・信州合同勉強会
Hokuriku.NET × JAZUG信州

Publié dans : Technologie
  • Soyez le premier à commenter

DeclarativeSql

  1. 1. Hokuriku.NET × JAZUG信州 -北陸・信州合同勉強会- DeclarativeSql - 属性ベーステーブルマッピングとSQLの自動生成 -
  2. 2. Name 鈴木 孝明 Twitter Account @xin9le Award Microsoft MVP for .NET Web Site http://xin9le.net About Me
  3. 3. ライブラリ作成のモチベーション Why declarative ?
  4. 4. Dapper 軽量で超高速なO/R Mapper POCOへのマッピングのみを請け負うので、SQLは完全直書き Entity Framework LINQによるDBアクセスからO/Rマッピングまでフルサポート SQLの直書きはないが、パッと使うには仰々しい感 Dapper vs Entity Framework
  5. 5. 昨今のチーム事情 けど 定型SQLは 楽したい チーム全員 SQL星人 でも LINQもEFも できない ってことは Dapper一択
  6. 6. そうだ、型情報からSQL作ろう
  7. 7. update Person set Age = @Age where Name = @Name and Sex = @Sex public class Person { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } public int Sex { get; set; } } こんな感じになったら嬉しい
  8. 8. 簡易な定型文のみをサポート 「それって何てEntity Framework?」にならないように 複雑なクエリが必要なときはSQL星人たちの神業に頼ればよい 自由度とメンテナンス性の両立 SQLの自動生成 = いくらかバグの混入を防ぐことができる 機能を求め過ぎて中途半端になるくらいならSQLの直書きも許容 求め過ぎないという割り切り
  9. 9. https://github.com/xin9le/DeclarativeSql It’s Free & Open Source PM> Install-Package DeclarativeSql.Core PM> Install-Package DeclarativeSql.Dapper
  10. 10. 「ちょっとの便利」を後押しするコア機能 DeclarativeSql.Core
  11. 11. using (var connection = DbProvider.CreateConnection(DbKind.SqlServer, "接続文字列")) { connection.Open(); //--- 何かデータベース操作 } EnumベースでのDB接続生成 対象DBを 引数で変更 可能 Oracle MySQL などもOK
  12. 12. using (var connection = DbProvider.CreateConnection(DbKind.Oracle, "接続文字列")) using (var transaction = connection.StartTransaction()) { //--- レコードの挿入/更新/削除など transaction.Complete(); } usingによるトランザクション Transaction Scopeと 同じ使い方
  13. 13. [Table("Person", Schema = "dbo")] //--- テーブル名の指定 public class Person { [Key] //--- 主キー [DatabaseGenerated(DatabaseGeneratedOption.Identity)] //--- 自動採番 public int Id { get; set; } [Required] //--- NotNull [Column("名前")] //--- 列名の指定 public string Name { get; set; } [Sequence("AgeSeq", Schema = "dbo")] //--- シーケンスの利用 (Oracleなどで) public int? Age { get; set; } [NotMapped] //--- マッピングしない public int Sex { get; set; } } 属性によるマッピング型定義 Code Firstと ほぼ同様
  14. 14. public sealed class TableMappingInfo { public Type Type { get; } //--- マッピングするクラスの型 public string Schema { get; } //--- テーブルのスキーマ名 public string Name { get; } //--- テーブル名 public IReadOnlyList<ColumnMappingInfo> Columns { get; } //--- 列マッピング情報 public static TableMappingInfo Create<T>(){ … }; //--- メタデータの取得 } マッピングメタデータの提供 #1 キャッシュ が効くので 高速
  15. 15. public sealed class ColumnMappingInfo { public string PropertyName { get; } //--- プロパティ名 public Type PropertyType { get; } //--- プロパティのデータ型 public string ColumnName { get; } //--- 列名 public DbType ColumnType { get; } //--- 列のデータ型 public bool IsPrimaryKey { get; } //--- 主キーかどうか public bool IsNullable { get; } //--- NULL許可かどうか public bool IsIdentity { get; } //--- 自動採番をするどうか public SequenceMappingInfo Sequence { get; } //--- 設定されているシーケンス情報 } マッピングメタデータの提供 #2
  16. 16. public sealed class SequenceMappingInfo { public string Schema { get; } //--- シーケンスのスキーマ名 public string Name { get; } //--- シーケンス名 } マッピングメタデータの提供 #3
  17. 17. //--- 指定の列のみを対象として全レコード取得 var sql = PrimitiveSql.CreateSelect<Person>(x => x.Id, x => x.Name); /* select Id as Id, 名前 as Name from dbo.Person */ プリミティブなSQLの生成 #1 指定がない 場合は 全列が対象
  18. 18. //--- 指定の列のみを対象として全レコードを更新 var sql = PrimitiveSql.CreateUpdate<Person>(DbKind.SqlServer, x => x.Name); /* update dbo.Person set 名前 = @Name */ プリミティブなSQLの生成 #2 Bind変数の 接頭辞の 決定に必要 指定がない 場合は 全列が対象
  19. 19. Dapperを基にした超簡単で直観的なCRUD操作 DeclarativeSql.Dapper
  20. 20. //--- 全件取得 var p1 = connection.Select<Person>(); //--- Id, Name 列に絞って全件取得 var p2 = connection.Select<Person>(x => x.Id, x => x.Name); //--- Id = 3 のレコードのみ取得 var p3 = connection.Select<Person>(x => x.Id == 3); //--- Id > 3 のレコードを Id, Name 列に絞って取得 var p4 = connection.Select<Person>(x => x.Id > 3, x => x.Id, x => x.Name); レコードの取得 .Select<T>
  21. 21. //--- 指定されたデータを挿入 var p5 = connection.Insert(new Person { Name = "xin9le", Age = 30 }); //--- 複数のレコードでもOK var p6 = connection.Insert(new [] { new Person { Name = "yoshiki", Age= 49, }, new Person { Name = "suzuki", Age= 30, }, new Person { Name = "anders", Age= 54, }, }); レコード挿入 .Insert<T>
  22. 22. //--- Age = 30 のレコードの Name 列を更新 var p7 = connection.Update ( new Person { Name = “xin9le" }, x => x.Age == 30, //--- 指定しなければ全レコード更新 x => x.Name //--- 指定がなければ全列更新 ); レコード更新 .Update<T>
  23. 23. //--- 全レコード削除 var p8 = connection.Delete<Person>(); //--- 年齢が30歳でないレコードを削除 var p9 = connection.Delete<Person>(x => x.Age != 30); //--- テーブルの切り捨て var p10 = connection.Truncate<Person>(); レコード削除 .Delete<T> .Truncate<T>
  24. 24. //--- メソッド名に ‘Async’ を付けるだけ var p1 = await connection.SelectAsync<Person>(); var p2 = await connection.InsertAsync(new Person { Name = "xin9le" }); var p3 = await connection.UpdateAsync(new Person { Name = "xin9le" }); var p4 = await connection.DeleteAsync<Person>(); もちろん非同期版も 実際に非同期処理になるかは各DBプロバイダーに依存する
  25. 25. Simple = Speed + Power Dapperの強みをそのままに、select * などの決まった手間を軽減 たった1文で書けるDBアクセス サポートしていない構文 inner join / left join / order by / group by / サブクエリー (etc.) やり過ぎは複雑さの増大と自由度の低下を招く シンプルに、そしてカジュアルに
  26. 26. Have a nice database operation!! Thank you

×