我研究了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;
答案 0 :(得分:5)
Dapper基本上跨越了ADO.NET作为一个非常薄的抽象 - 所以理论上它不能比编写良好的ADO.NET代码更快(尽管说实话:大多数人不要编写写得很好的ADO.NET代码。)
但它可能几乎无法区分;假设您正在使用只是 Dapper(不是任何位于其上的东西),那么它不包括任何查询生成,表达式树/ DSL解析,复杂模型配置,或任何其他倾向于使完整ORM更灵活但更昂贵的东西。
相反:它只关注执行用户提供的查询和映射结果;它的作用是生成所有的实现代码(如何将MerchantProduct
映射到您的列)通过IL-emit和缓存到某处。同样,它以相同的方式准备了大部分参数准备代码。所以在运行时,通常只从缓存中获取两个委托实例并调用它们。
由于(RDBMS的延迟+查询执行成本+结果的网络带宽成本)的组合将远远高于从字典中提取两个代理的开销,我们可以本质上忽略那个成本。
简而言之:您可以在这里衡量一笔巨大的开销。
作为代码的次要优化:首选AsList()
至ToList()
以避免创建副本。
答案 1 :(得分:3)
Dapper是micro-ORM或Data Mapper。它内部使用ADO.NET。此外,Dapper将ADO.NET数据结构(例如DataReader
)映射到您的自定义POCO类。因为这是额外的工作 Dapper,理论上它不能比ADO.NET更快。
从comments(@MarcGravell)之一复制以下this答案:
它不能比它所处的原始API更快;但是,它可能比典型的ADO.NET消费代码更快 - 大多数消耗ADO.NET的代码往往写得很糟糕,效率低下等;甚至不让我开始
DataTable
:)
假设在比较时以优化的方式正确使用ADO.NET。否则,结果可能相反;但这不是ADO.NET的错。如果ADO.NET使用不正确,它可能比Dapper表现不佳。这是在使用ADO.NET直接绕过Dapper时发生的情况。
与ADO.NET相比,大多数情况下的Dapper表现相同(差别可以忽略不计)。 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)的性能比较statistics;如果您有兴趣,请查看。