1つのクラスのMicro-ORM

こんにちは、愛するhabravchane!



ADO.NETでの自分のバイクチューニングについてお話ししたいと思います。

私はほとんどのプロジェクトのデータをストアドプロシージャで実装しているため、「複雑な」結果を読み取る必要があるため、アドインを作成するアイデアが現れました。たとえば、マスターテーブルといくつかの下位から選択し、このデータをモデルに入力します。



誰かが興味を持っているなら、カットをお願いします





マッピングは、ILコードを生成してDataRecordから目的のタイプを初期化し、静的ディクショナリに保存することにより実行されます。これにより、DataManager自体のインスタンスに関係なく、呼び出されるストアドプロシージャを考慮して、このタイプの初期化コードを再生成する必要がなくなります。



使用例:



データベースへの接続の作成を実装するクラス相続人を作成しましょう:

class MSSqlDataManager : DataManager { public MSSqlDataManager() : base(new SqlConnection("ConnectionString here")) { } }
      
      







簡単なデータセットの取得:

 public class Product { public int Id { get; set; } public string Name { get; set; } public string Description { get; set; } public int? Price { get; set; } } ... using (var dm = new MSSqlDataManager()) { List<Product> res = dm.Procedure("Test").GetList<Product>(); }
      
      





ここで、テストストレージは、たとえば次の種類のデータを選択します。

 SELECT p.Id, p.Name, p.[Description], p.Price FROM dbo.Product p
      
      





からのデータの読み取り

ストレージ
 SELECT p.Id , p.Name, , p.[Description] , p.Price , StorageId = s.Id , StorageName = s.Name FROM dbo.Product p INNER JOIN dbo.Storages s ON s.Id = p.StorageId WHERE p.Id = @Id; SELECT c.Id , c.Body , c.WriteDate , UserId = u.Id , UserName = u.Name , UserLocationId = l.Id , UserLocationName = l.Name , c.ProductId FROM dbo.Comments c INNER JOIN dbo.Users u ON u.Id = c.UserId INNER JOIN dbo.Locations l ON l.Id = u.LocationId WHERE c.ProductId = @Id;
      
      







1つのマスターレコードと複数の部下を選択します。

 Product res = dm.Procedure("Test").AddParams(new { id = 10 }).Get<Product, ProductComment>(p => p.Comments);
      
      





モデルクラスの構造はどこですか

そのような
 public class UserLocation { public int Id { get; set; } public string Name { get; set; } } public class UserModel { public int Id { get; set; } public string Name { get; set; } public UserLocation Location { get; set; } public UserModel() { this.Location = new UserLocation(); } } public class ProductComment { public int Id { get; set; } public string Body { get; set; } public DateTime WriteDate { get; set; } public UserModel User { get; set; } public int ProductId { get; set; } public ProductComment() { this.User = new UserModel(); } } public class ProductStorage { public int Id { get; set; } public string Name { get; set; } } public class Product { public int Id { get; set; } public string Name { get; set; } public string Description { get; set; } public int? Price { get; set; } public ProductStorage Storage { get; set; } public List<ProductComment> Comments { get; set; } public Product() { this.Storage = new ProductStorage(); this.Comments = new List<ProductComment>(); } }
      
      







クラスのメインプロパティに加えて、プロパティとネストされたプロパティクラスも初期化されることに注意してください。 これを行うには、選択の列名に正しい名前を割り当てる必要があります。これは、ネストを反映しています-たとえば、UserLocationNameの場合、マッピングが実行されるオブジェクト(この場合はProductCommentタイプ)、ユーザープロパティ、その中の場所、および既に必要な名前をマッパーが見つけることができます。



もっともっと。 部下を持つ複数のマスターレコードの取得:

 List<Product> res = dm.Procedure("Test") .GetList<Product, ProductComment>( (parents, detail)=>parents.First(p => p.Id == detail.ProductId).Comments );
      
      





合計で、1対多および多対多のレコードを取得する4つのオーバーロードメソッドを発表し、最大4セットの従属レコードを読み取ることができました。 より多くの下位セットがある場合(非常にまれです)、オーバーロードを追加するか、別の方法を使用できます。

 List<Product> res = dm.Procedure("Test") .GetList<Product>( (dr, parents) => { parents.Where(p=>p.Id == (int)dr["ProductId"]).First().Comments .Add(dm.Create<ProductComment>(dr)); }, (dr, parents) => { }, ... );
      
      





データモデルが上記のテンプレートに適合しない場合は、Rawメソッドを使用できます。IDataReaderが使用可能なラムダを受け入れ、状況に応じて使用できます。

 dm.Procedure("Test") .Raw(dr => { while (dr.Read()) { ... } });
      
      





もちろん、スカラー値と古き良きExecuteを取得する方法があります。

ストレージのパラメーターを追加するには、AddParamsを呼び出します。

 dm.AddParams(new { id = 10, name = "stringparam", writeDate = DateTime.Now }) ...
      
      





テーブル値パラメーター(テーブル値パラメーター)を送信するメソッドも実装されています-もちろん、2008バージョン以降のMS SQL Serverでのみ機能します。

 dm.AddEnumerableParam("Details", Enumerable.Range(1, 10) .Select(e => new {id = e, name = string.Concat("Name", e.ToString())}) );
      
      







パフォーマンスでは、特に歌手でオブジェクト初期化子を呼び出す場合、Dapperに少し遅れています。

計画は、パラメーターをストレージに渡すIQueryable結果のサポートを実装することです。これは、ApiControllerのAspNet MVCで非常に便利です。



誰かがこの自転車に興味がある場合、ライブラリコードはgithubで入手できます。

ご清聴ありがとうございました!



All Articles