Commit 01c6a139 authored by Nick Craver's avatar Nick Craver

Merge remote-tracking branch 'origin/master' into netstandard2

parents 6904fa4e 610d8f65
......@@ -458,10 +458,9 @@ public async Task<int> InsertAsync(IDbConnection connection, IDbTransaction tran
// Return the key by assinging the corresponding property in the object - by product is that it supports compound primary keys
var id = 0;
var values = results.First();
foreach (var p in propertyInfos)
{
var value = values[p.Name.ToLower()];
var value = ((IDictionary<string, object>)results.First())[p.Name.ToLower()];
p.SetValue(entityToInsert, value, null);
if (id == 0)
id = Convert.ToInt32(value);
......
......@@ -15,7 +15,7 @@ public void Setup()
_mapper = new QueryMapper(ConnectionString);
}
[Benchmark(Description = "ExecuteReader", OperationsPerInvoke = Iterations)]
[Benchmark(Description = "ExecuteReader")]
public async Task ExecuteReader()
{
Step();
......
......@@ -12,46 +12,46 @@ public void Setup()
BaseSetup();
}
[Benchmark(Description = "Query<T> (buffered)", OperationsPerInvoke = Iterations)]
[Benchmark(Description = "Query<T> (buffered)")]
public Post QueryBuffered()
{
Step();
return _connection.Query<Post>("select * from Posts where Id = @Id", new { Id = i }, buffered: true).First();
}
[Benchmark(Description = "Query<dyanmic> (buffered)", OperationsPerInvoke = Iterations)]
[Benchmark(Description = "Query<dyanmic> (buffered)")]
public dynamic QueryBufferedDynamic()
{
Step();
return _connection.Query("select * from Posts where Id = @Id", new { Id = i }, buffered: true).First();
}
[Benchmark(Description = "Query<T> (unbuffered)", OperationsPerInvoke = Iterations)]
[Benchmark(Description = "Query<T> (unbuffered)")]
public Post QueryUnbuffered()
{
Step();
return _connection.Query<Post>("select * from Posts where Id = @Id", new { Id = i }, buffered: false).First();
}
[Benchmark(Description = "Query<dyanmic> (unbuffered)", OperationsPerInvoke = Iterations)]
[Benchmark(Description = "Query<dyanmic> (unbuffered)")]
public dynamic QueryUnbufferedDynamic()
{
Step();
return _connection.Query("select * from Posts where Id = @Id", new { Id = i }, buffered: false).First();
}
[Benchmark(Description = "QueryFirstOrDefault<T>", OperationsPerInvoke = Iterations)]
[Benchmark(Description = "QueryFirstOrDefault<T>")]
public Post QueryFirstOrDefault()
{
Step();
return _connection.QueryFirstOrDefault<Post>("select * from Posts where Id = @Id", new { Id = i });
}
[Benchmark(Description = "QueryFirstOrDefault<dyanmic>", OperationsPerInvoke = Iterations)]
[Benchmark(Description = "QueryFirstOrDefault<dyanmic>")]
public dynamic QueryFirstOrDefaultDynamic()
{
Step();
return _connection.QueryFirstOrDefault("select * from Posts where Id = @Id", new { Id = i }).First();
}
[Benchmark(Description = "Contrib Get<T>", OperationsPerInvoke = Iterations)]
[Benchmark(Description = "Contrib Get<T>")]
public Post ContribGet()
{
Step();
......
using BenchmarkDotNet.Attributes;
using Dapper.Tests.Performance.Linq2Sql;
using System;
using System.Data.Linq;
using System.Linq;
namespace Dapper.Tests.Performance
......@@ -9,8 +6,6 @@ namespace Dapper.Tests.Performance
public class EF6Benchmarks : BenchmarkBase
{
private EntityFramework.EFContext Context;
private static readonly Func<DataClassesDataContext, int, Linq2Sql.Post> compiledQuery =
CompiledQuery.Compile((DataClassesDataContext ctx, int id) => ctx.Posts.First(p => p.Id == id));
[GlobalSetup]
public void Setup()
......@@ -19,21 +14,21 @@ public void Setup()
Context = new EntityFramework.EFContext(_connection);
}
[Benchmark(Description = "Normal", OperationsPerInvoke = Iterations)]
[Benchmark(Description = "Normal")]
public Post Normal()
{
Step();
return Context.Posts.First(p => p.Id == i);
}
[Benchmark(Description = "SqlQuery", OperationsPerInvoke = Iterations)]
[Benchmark(Description = "SqlQuery")]
public Post SqlQuery()
{
Step();
return Context.Database.SqlQuery<Post>("select * from Posts where Id = {0}", i).First();
}
[Benchmark(Description = "No Tracking", OperationsPerInvoke = Iterations)]
[Benchmark(Description = "No Tracking")]
public Post NoTracking()
{
Step();
......
using BenchmarkDotNet.Attributes;
using Dapper.Tests.Performance.Linq2Sql;
using Microsoft.EntityFrameworkCore;
using System;
using System.Data.Linq;
using System.Linq;
namespace Dapper.Tests.Performance
{
public class EFCoreBenchmarks : BenchmarkBase
{
private EntityFrameworkCore.EFCoreContext Context;
private static readonly Func<DataClassesDataContext, int, Linq2Sql.Post> compiledQuery =
CompiledQuery.Compile((DataClassesDataContext ctx, int id) => ctx.Posts.First(p => p.Id == id));
[GlobalSetup]
public void Setup()
{
BaseSetup();
Context = new EntityFrameworkCore.EFCoreContext(_connection.ConnectionString);
}
[Benchmark(Description = "Normal")]
public Post Normal()
{
Step();
return Context.Posts.First(p => p.Id == i);
}
[Benchmark(Description = "SqlQuery")]
public Post SqlQuery()
{
Step();
return Context.Posts.FromSql("select * from Posts where Id = {0}", i).First();
}
[Benchmark(Description = "No Tracking")]
public Post NoTracking()
{
Step();
return Context.Posts.AsNoTracking().First(p => p.Id == i);
}
}
}
\ No newline at end of file
......@@ -47,7 +47,7 @@ public void Setup()
#endif
}
[Benchmark(Description = "SqlCommand", OperationsPerInvoke = Iterations, Baseline = true)]
[Benchmark(Description = "SqlCommand", Baseline = true)]
public Post SqlCommand()
{
Step();
......@@ -75,7 +75,7 @@ public Post SqlCommand()
}
}
[Benchmark(Description = "DataTable", OperationsPerInvoke = Iterations)]
[Benchmark(Description = "DataTable")]
public dynamic DataTableDynamic()
{
Step();
......
......@@ -19,21 +19,21 @@ public void Setup()
Linq2SqlContext = new DataClassesDataContext(_connection);
}
[Benchmark(Description = "Normal", OperationsPerInvoke = Iterations)]
[Benchmark(Description = "Normal")]
public Linq2Sql.Post Normal()
{
Step();
return Linq2SqlContext.Posts.First(p => p.Id == i);
}
[Benchmark(Description = "Compiled", OperationsPerInvoke = Iterations)]
[Benchmark(Description = "Compiled")]
public Linq2Sql.Post Compiled()
{
Step();
return compiledQuery(Linq2SqlContext, i);
}
[Benchmark(Description = "ExecuteQuery", OperationsPerInvoke = Iterations)]
[Benchmark(Description = "ExecuteQuery")]
public Post ExecuteQuery()
{
Step();
......
......@@ -15,7 +15,7 @@ public void Setup()
_model = new DynamicModel(ConnectionString);
}
[Benchmark(Description = "Query (dynamic)", OperationsPerInvoke = Iterations)]
[Benchmark(Description = "Query (dynamic)")]
public dynamic QueryDynamic()
{
Step();
......
......@@ -24,7 +24,7 @@ public void Setup()
_get = NHibernateHelper.OpenSession();
}
[Benchmark(Description = "SQL", OperationsPerInvoke = Iterations)]
[Benchmark(Description = "SQL")]
public Post SQL()
{
Step();
......@@ -34,7 +34,7 @@ public Post SQL()
.List<Post>()[0];
}
[Benchmark(Description = "HQL", OperationsPerInvoke = Iterations)]
[Benchmark(Description = "HQL")]
public Post HQL()
{
Step();
......@@ -43,7 +43,7 @@ public Post HQL()
.List<Post>()[0];
}
[Benchmark(Description = "Criteria", OperationsPerInvoke = Iterations)]
[Benchmark(Description = "Criteria")]
public Post Criteria()
{
Step();
......@@ -52,14 +52,14 @@ public Post Criteria()
.List<Post>()[0];
}
[Benchmark(Description = "LINQ", OperationsPerInvoke = Iterations)]
[Benchmark(Description = "LINQ")]
public Post LINQ()
{
Step();
return _linq.Query<Post>().First(p => p.Id == i);
}
[Benchmark(Description = "Get<T>", OperationsPerInvoke = Iterations)]
[Benchmark(Description = "Get<T>")]
public Post Get()
{
Step();
......
......@@ -21,14 +21,14 @@ public void Setup()
_dbFast.ForceDateTimesToUtc = false;
}
[Benchmark(Description = "Fetch<T>", OperationsPerInvoke = Iterations)]
[Benchmark(Description = "Fetch<Post>")]
public Post Fetch()
{
Step();
return _db.Fetch<Post>("SELECT * from Posts where Id=@0", i).First();
}
[Benchmark(Description = "(Fast) Fetch<T>", OperationsPerInvoke = Iterations)]
[Benchmark(Description = "Fetch<Post> (Fast)")]
public Post FetchFast()
{
Step();
......
......@@ -16,7 +16,7 @@ public void Setup()
_db = dbFactory.Open();
}
[Benchmark(Description = "SingleById<T>", OperationsPerInvoke = Iterations)]
[Benchmark(Description = "SingleById")]
public Post Query()
{
Step();
......
......@@ -13,7 +13,7 @@ public void Setup()
_sdb = Simple.Data.Database.OpenConnection(ConnectionString);
}
[Benchmark(Description = "FindById (dynamic)", OperationsPerInvoke = Iterations)]
[Benchmark(Description = "FindById")]
public dynamic QueryDynamic()
{
Step();
......
......@@ -25,7 +25,7 @@ public void Setup()
_db = new DatabaseManager(_connection);
}
[Benchmark(Description = "Mapping Cache<T>", OperationsPerInvoke = Iterations)]
[Benchmark(Description = "Mapping Cache")]
public Post MappingCache()
{
Step();
......@@ -35,7 +35,7 @@ public Post MappingCache()
.Execute(_db, new { Id = i }).First();
}
[Benchmark(Description = "Mapping Cache (dynamic)", OperationsPerInvoke = Iterations)]
[Benchmark(Description = "Mapping Cache (dynamic)")]
public dynamic MappingCacheDynamic()
{
Step();
......@@ -45,14 +45,14 @@ public dynamic MappingCacheDynamic()
.Execute(_db, new { Id = i }).First();
}
[Benchmark(Description = "Mapping Static<T>", OperationsPerInvoke = Iterations)]
[Benchmark(Description = "Mapping Static")]
public Post MappingStatic()
{
Step();
return _cmd.Execute(_db, new { Id = i }).First();
}
[Benchmark(Description = "Mapping Static (dynamic)", OperationsPerInvoke = Iterations)]
[Benchmark(Description = "Mapping Static (dynamic)")]
public dynamic MappingStaticDynamic()
{
Step();
......
......@@ -46,10 +46,12 @@ public Config()
Add(new ORMColum());
Add(new ReturnColum());
Add(Job.Default
.WithUnrollFactor(BenchmarkBase.Iterations)
//.WithIterationTime(new TimeInterval(500, TimeUnit.Millisecond))
.WithLaunchCount(1)
.WithIterationTime(new TimeInterval(500, TimeUnit.Millisecond))
.WithWarmupCount(3)
.WithTargetCount(3)
.WithWarmupCount(0)
.WithTargetCount(5)
.WithRemoveOutliers(true)
);
}
}
......
......@@ -17,6 +17,8 @@
<!--<PackageReference Include="BLToolkit" Version="4.3.6" />-->
<PackageReference Include="EntityFramework" Version="6.1.3" />
<PackageReference Include="FirebirdSql.Data.FirebirdClient" Version="5.9.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="1.1.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="1.1.2" />
<PackageReference Include="Microsoft.SqlServer.Compact" Version="4.0.8876.1" />
<PackageReference Include="Microsoft.SqlServer.Types" Version="14.0.314.76" />
<PackageReference Include="MySql.Data" Version="7.0.7-m61" />
......
using Microsoft.EntityFrameworkCore;
namespace Dapper.Tests.Performance.EntityFrameworkCore
{
public class EFCoreContext : DbContext
{
private readonly string _connectionString;
public EFCoreContext(string connectionString)
{
_connectionString = connectionString;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => optionsBuilder.UseSqlServer(_connectionString);
public DbSet<Post> Posts { get; set; }
}
}
\ No newline at end of file
......@@ -19,6 +19,8 @@
using Susanoo;
using System.Configuration;
using System.Threading.Tasks;
using Dapper.Tests.Performance.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
namespace Dapper.Tests.Performance
{
......@@ -143,16 +145,23 @@ public async Task RunAsync(int iterations)
var entityContext2 = new EFContext(connection);
tests.Add(id => entityContext2.Database.SqlQuery<Post>("select * from Posts where Id = {0}", id).First(), "Entity Framework: SqlQuery");
var entityContext3 = new EFContext(connection);
tests.Add(id => entityContext3.Posts.AsNoTracking().First(p => p.Id == id), "Entity Framework: No Tracking");
}, "Entity Framework");
//var entityContext3 = new EFContext(connection);
//tests.Add(id => entityFrameworkCompiled(entityContext3, id), "Entity Framework CompiledQuery");
// Entity Framework Core
Try(() =>
{
var entityContext = new EFCoreContext(ConnectionString);
tests.Add(id => entityContext.Posts.First(p => p.Id == id), "Entity Framework Core");
//var entityContext4 = new EFContext(connection);
//tests.Add(id => entityContext4.Posts.Where("it.Id = @id", new System.Data.Objects.ObjectParameter("id", id)).First(), "Entity Framework ESQL");
var entityContext2 = new EFCoreContext(ConnectionString);
tests.Add(id => entityContext2.Posts.FromSql("select * from Posts where Id = {0}", id).First(), "Entity Framework Core: FromSql");
var entityContext5 = new EFContext(connection);
tests.Add(id => entityContext5.Posts.AsNoTracking().First(p => p.Id == id), "Entity Framework: No Tracking");
}, "Entity Framework");
var entityContext3 = new EFContext(connection);
tests.Add(id => entityContext3.Posts.AsNoTracking().First(p => p.Id == id), "Entity Framework Core: No Tracking");
}, "Entity Framework Core");
// Dapper
Try(() =>
......
......@@ -120,111 +120,41 @@ The performance tests are broken in to 3 lists:
### Performance of SELECT mapping over 500 iterations - POCO serialization
<table>
<tr>
<th>Method</th>
<th>Duration</th>
<th>Remarks</th>
</tr>
<tr>
<td>Hand coded (using a <code>SqlDataReader</code>)</td>
<td>47ms</td>
<td rowspan="9"><a href="http://www.toptensoftware.com/blog/posts/94-PetaPoco-More-Speed">Can be faster</a></td>
</tr>
<tr>
<td>Dapper <code>ExecuteMapperQuery<Post></code></td>
<td>49ms</td>
</tr>
<tr>
<td><a href="https://github.com/ServiceStack/ServiceStack.OrmLite">ServiceStack.OrmLite</a> (QueryById)</td>
<td>50ms</td>
</tr>
<tr>
<td><a href="http://www.toptensoftware.com/petapoco/">PetaPoco</a></td>
<td>52ms</td>
</tr>
<tr>
<td>BLToolkit</td>
<td>80ms</td>
</tr>
<tr>
<td>SubSonic CodingHorror</td>
<td>107ms</td>
</tr>
<tr>
<td>NHibernate SQL</td>
<td>104ms</td>
</tr>
<tr>
<td>Linq 2 SQL <code>ExecuteQuery</code></td>
<td>181ms</td>
</tr>
<tr>
<td>Entity framework <code>ExecuteStoreQuery</code></td>
<td>631ms</td>
</tr>
</table>
| Method | Duration | Remarks |
| --------------------------------------------------- | -------- | ------- |
| Hand coded (using a `SqlDataReader`) | 47ms |
| Dapper `ExecuteMapperQuery` | 49ms |
| [ServiceStack.OrmLite](https://github.com/ServiceStack/ServiceStack.OrmLite) (QueryById) | 50ms |
| [PetaPoco](http://www.toptensoftware.com/petapoco/) | 52ms | [Can be faster](http://www.toptensoftware.com/blog/posts/94-PetaPoco-More-Speed) |
| BLToolkit | 80ms |
| SubSonic CodingHorror | 107ms |
| NHibernate SQL | 104ms |
| Linq 2 SQL `ExecuteQuery` | 181ms |
| Entity framework `ExecuteStoreQuery` | 631ms |
### Performance of SELECT mapping over 500 iterations - dynamic serialization
<table>
<tr>
<th>Method</th>
<th>Duration</th>
<th>Remarks</th>
</tr>
<tr>
<td>Dapper <code>ExecuteMapperQuery</code> (dynamic)</td>
<td>48ms</td>
<td rowspan="3">&nbsp;</td>
</tr>
<tr>
<td><a href="https://github.com/FransBouma/Massive">Massive</a></td>
<td>52ms</td>
</tr>
<tr>
<td><a href="https://github.com/markrendle/Simple.Data">Simple.Data</a></td>
<td>95ms</td>
</tr>
</table>
| Method | Duration | Remarks |
| -------------------------------------------------------- | -------- | ------- |
| Dapper `ExecuteMapperQuery` (dynamic) | 48ms |
| [Massive](https://github.com/FransBouma/Massive) | 52ms |
| [Simple.Data](https://github.com/markrendle/Simple.Data) | 95ms |
### Performance of SELECT mapping over 500 iterations - typical usage
<table>
<tr>
<th>Method</th>
<th>Duration</th>
<th>Remarks</th>
</tr>
<tr>
<td>Linq 2 SQL CompiledQuery</td>
<td>81ms</td>
<td>Not super typical involves complex code</td>
</tr>
<tr>
<td>NHibernate HQL</td>
<td>118ms</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>Linq 2 SQL</td>
<td>559ms</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>Entity framework</td>
<td>859ms</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>SubSonic ActiveRecord.SingleOrDefault</td>
<td>3619ms</td>
<td>&nbsp;</td>
</tr>
</table>
Performance benchmarks are available [here](https://github.com/StackExchange/dapper-dot-net/blob/master/Dapper.Tests.Performance/PerformanceTests.cs).
| Method | Duration | Remarks |
| ------------------------------------- | -------- | ------- |
| Linq 2 SQL CompiledQuery | 81ms | Not super typical involves complex code |
| NHibernate HQL | 118ms |
| Linq 2 SQL | 559ms |
| Entity framework | 859ms |
| SubSonic ActiveRecord.SingleOrDefault | 3619ms |
Performance benchmarks are available [here](https://github.com/StackExchange/Dapper/tree/master/Dapper.Tests.Performance).
Feel free to submit patches that include other ORMs - when running benchmarks, be sure to compile in Release and not attach a debugger (ctrl F5).
......@@ -425,7 +355,7 @@ Dapper's simplicity means that many feature that ORMs ship with are stripped out
Will Dapper work with my DB provider?
---------------------
Dapper has no DB specific implementation details, it works across all .NET ADO providers including [SQLite](http://www.sqlite.org/), SQL CE, Firebird, Oracle, MySQL, PostgreSQL and SQL Server.
Dapper has no DB specific implementation details, it works across all .NET ADO providers including [SQLite](https://www.sqlite.org/), SQL CE, Firebird, Oracle, MySQL, PostgreSQL and SQL Server.
Do you have a comprehensive list of examples?
---------------------
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment