DapperとADO.NETについて調べ、両方で選択テストを実行したところ、ADO.NETがDapperよりも高速である場合と、逆になっている場合があることがわかりました。 SQL Serverを使用しているため、これがデータベースの問題である可能性があることを理解しています。リフレクションが遅いと述べられているように、私はADO.NETでリフレクションを使用しています。では、どちらのアプローチが最速か教えてもらえますか?
ここで私がコーディングしたもの。
ADO.NETの使用
DashboardResponseModel dashResp = null;
SqlConnection conn = new SqlConnection(connStr);
try
{
SqlCommand cmd = new SqlCommand("spGetMerchantDashboard", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@MID", mid);
conn.Open();
var dr = cmd.ExecuteReader();
List<MerchantProduct> lstMerProd = dr.MapToList<MerchantProduct>();
List<MerchantPayment> lstMerPay = dr.MapToList<MerchantPayment>();
if (lstMerProd != null || lstMerPay != null)
{
dashResp = new DashboardResponseModel();
dashResp.MerchantProduct = lstMerProd == null ? new
List<MerchantProduct>() : lstMerProd;
dashResp.MerchantPayment = lstMerPay == null ? new
List<MerchantPayment>() : lstMerPay;
}
dr.Close();
}
return dashResp;
Dapperの使用
DashboardResponseModel dashResp = null;
var multipleresult = db.QueryMultiple("spGetMerchantDashboard", new { mid =
mid }, commandType: CommandType.StoredProcedure);
var merchantproduct = multipleresult.Read<MerchantProduct>().ToList();
var merchantpayment = multipleresult.Read<MerchantPayment>().ToList();
if (merchantproduct.Count > 0 || merchantpayment.Count > 0)
dashResp = new DashboardResponseModel { MerchantProduct =
merchantproduct, MerchantPayment = merchantpayment };
return dashResp;
Dapperは基本的に非常に薄い抽象化としてADO.NETにまたがっています-したがって、理論的には、よく書かれたADO.NETコードよりも高速できません(正直なところ、ほとんどの人しないでください) writeよく書かれたADO.NETコード)。
それは事実上区別がつかないかもしれませんが; just Dapper(その上にあるものではない)を使用していると仮定すると、クエリ生成、式ツリー/ DSL解析、複雑なモデル構成、または完全なORMをより柔軟にする傾向があるが、より高価にする傾向がある他のこと。
代わりに、ユーザー指定のクエリの実行と結果のマッピングのみに焦点を当てています。それが行うことは、IL-emitを介してすべてのマテリアライゼーションコード(MerchantProduct
を列にマップする方法)を生成し、それをどこかにキャッシュすることです。同様に、パラメータ準備コードの多くを同じ方法で準備します。したがって、実行時は通常キャッシュから2つのデリゲートインスタンスをフェッチして呼び出すだけです。
(RDBMSへのレイテンシ+クエリ実行コスト+結果のネットワーク帯域幅コスト)の組み合わせは、ディクショナリから2つのデリゲートをフェッチするオーバーヘッドよりもはるかに高くなるため、本質的にそのコストを無視できます。 。
つまり、ここでかなりのオーバーヘッドを測定できることはまれです。
コードのマイナーな最適化として:コピーの作成を避けるために、AsList()
よりもToList()
を優先します。
Dapperはmicro-ORMまたはデータマッパーです。内部的にはADO.NETを使用します。さらに、DapperはADO.NETデータ構造(たとえばDataReader
)をカスタムPOCOクラスにマップします。これは追加の作業であるため、理論的には、DapperはADO.NETよりも高速にすることはできません。
以下は、 comments (@ MarcGravell)for this answerの1つからコピーされたものです。
その上にある生のAPIよりも速くすることはできません。ただし、通常のADO.NETを消費するコードよりも高速になる可能性があります。ADO.NETを消費するほとんどのコードは、記述が不十分で非効率的である傾向があります。
DataTable
を始めないでください:)
この比較では、ADO.NETが最適化された方法で適切に使用されていることを前提としています。そうしないと、結果が逆になる可能性があります。しかし、それはADO.NETのせいではありません。 ADO.NETが正しく使用されていない場合、Dapperよりもパフォーマンスが低下する可能性があります。これは、Dapperを直接バイパスしてADO.NETを使用しているときに発生します。
ほとんどの場合、DapperはADO.NETと比較して同等のパフォーマンス(ごくわずかな違い)を示します。 Dapperは、その範囲内にあるADO.NETに推奨される多くの最適化を内部的に実装します。また、最終的にパフォーマンス(およびセキュリティ)を向上させる多くの優れたADO.NETコーディングプラクティスを強制します。
マッピングはDapperのコア部分であるため、ILを使用することで大幅に最適化されます。これにより、Dapperは、コードで手動でマッピングするよりも優れた選択肢になります。
Dapperがどのように発明され、パフォーマンスのためにどのように最適化されているかを説明しているこのブログを参照してください: https://samsaffron.com/archive/2011/03/30/How+I+learned+to+stop+worrying+and + write + my + own + ORM
返されるデータ構造が十分に大きい場合(マッピング時間が長くなります)、Dapperはわずかに遅くなります。ただし、これはADO.NETにも同様に当てはまります。前に述べたように、Dapperのマッパー部分は大幅に最適化されています。したがって、コードで手動でマッピングするよりも優れた選択です。さらに、Dapperはbuffered
パラメーターを提供します。 false
に設定すると、Dapperはリストを実体化しません。イテレータで各アイテムを渡すだけです。 @Marcによるこの回答へのコメントを参照してください。
Dapperは、IDbConnection
に書き込まれるため、プロバイダー固有の機能を実装していません。これは、非常にまれなケースでパフォーマンスに影響を与える可能性があります。ただし、これは、Dapperにこれを行う方法を指示するインターフェイスを実装する場合に実行できます。
Dapperはステートメントの準備をサポートしていません。ごくまれに問題になる場合があります。 this ブログを読んでください。
このわずかでまれなパフォーマンスの低下により、強く型付けされたデータ構造や、はるかに少なくて管理しやすいコードなど、大きなメリットが得られます。これは本当に大きな利益です。
ネット上で利用可能なDapper(他のORMおよびADO.NETとの)の多くのパフォーマンス比較 統計 があります。興味のある方のためにご覧ください。