PageRenderTime 49ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/Dapper.Tests.Performance/LegacyTests.cs

https://bitbucket.org/Ecarestia/dapper
C# | 403 lines | 320 code | 54 blank | 29 comment | 12 complexity | ee28f3a22ab45c6d8a54bd55db18ac72 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Data.Linq;
  5. using System.Data.SqlClient;
  6. using System.Diagnostics;
  7. using System.Linq;
  8. //using BLToolkit.Data; // Note: this doesn't load in the new .csproj system...likely a bug
  9. using Dapper.Tests.Performance.EntityFramework;
  10. using Dapper.Tests.Performance.Linq2Sql;
  11. using Dapper.Tests.Performance.NHibernate;
  12. using Dapper.Contrib.Extensions;
  13. using Massive;
  14. using NHibernate.Criterion;
  15. using NHibernate.Linq;
  16. using ServiceStack.OrmLite;
  17. using ServiceStack.OrmLite.Dapper;
  18. using Susanoo;
  19. using System.Configuration;
  20. using System.Threading.Tasks;
  21. using Dapper.Tests.Performance.EntityFrameworkCore;
  22. using Microsoft.EntityFrameworkCore;
  23. namespace Dapper.Tests.Performance
  24. {
  25. public class LegacyTests
  26. {
  27. private class Test
  28. {
  29. public Test(Action<int> iteration, string name)
  30. {
  31. Iteration = iteration;
  32. Name = name;
  33. }
  34. public Test(Func<int, Task> iterationAsync, string name)
  35. {
  36. IterationAsync = iterationAsync;
  37. Name = name;
  38. }
  39. public Action<int> Iteration { get; set; }
  40. public Func<int, Task> IterationAsync { get; set; }
  41. public string Name { get; set; }
  42. public Stopwatch Watch { get; set; }
  43. }
  44. private class Tests : List<Test>
  45. {
  46. public void Add(Action<int> iteration, string name)
  47. {
  48. Add(new Test(iteration, name));
  49. }
  50. public void AsyncAdd(Func<int, Task> iterationAsync, string name)
  51. {
  52. Add(new Test(iterationAsync, name));
  53. }
  54. public async Task RunAsync(int iterations)
  55. {
  56. // warmup
  57. foreach (var test in this)
  58. {
  59. test.Iteration?.Invoke(iterations + 1);
  60. if (test.IterationAsync != null) await test.IterationAsync(iterations + 1).ConfigureAwait(false);
  61. test.Watch = new Stopwatch();
  62. test.Watch.Reset();
  63. }
  64. var rand = new Random();
  65. for (int i = 1; i <= iterations; i++)
  66. {
  67. foreach (var test in this.OrderBy(ignore => rand.Next()))
  68. {
  69. test.Watch.Start();
  70. test.Iteration?.Invoke(i);
  71. if (test.IterationAsync != null) await test.IterationAsync(i).ConfigureAwait(false);
  72. test.Watch.Stop();
  73. }
  74. }
  75. foreach (var test in this.OrderBy(t => t.Watch.ElapsedMilliseconds))
  76. {
  77. var ms = test.Watch.ElapsedMilliseconds.ToString();
  78. Console.Write(ms);
  79. Program.WriteColor("ms ".PadRight(8 - ms.Length), ConsoleColor.DarkGray);
  80. Console.WriteLine(test.Name);
  81. }
  82. }
  83. }
  84. public static string ConnectionString { get; } = ConfigurationManager.ConnectionStrings["Main"].ConnectionString;
  85. public static SqlConnection GetOpenConnection()
  86. {
  87. var connection = new SqlConnection(ConnectionString);
  88. connection.Open();
  89. return connection;
  90. }
  91. private static DataClassesDataContext GetL2SContext(SqlConnection connection) =>
  92. new DataClassesDataContext(connection);
  93. private static void Try(Action action, string blame)
  94. {
  95. try
  96. {
  97. action();
  98. }
  99. catch (Exception ex)
  100. {
  101. Console.Error.WriteLine($"{blame}: {ex.Message}");
  102. }
  103. }
  104. public async Task RunAsync(int iterations)
  105. {
  106. using (var connection = GetOpenConnection())
  107. {
  108. #pragma warning disable IDE0017 // Simplify object initialization
  109. #pragma warning disable RCS1121 // Use [] instead of calling 'First'.
  110. var tests = new Tests();
  111. // Linq2SQL
  112. Try(() =>
  113. {
  114. var l2scontext1 = GetL2SContext(connection);
  115. tests.Add(id => l2scontext1.Posts.First(p => p.Id == id), "Linq2Sql: Normal");
  116. var l2scontext2 = GetL2SContext(connection);
  117. var compiledGetPost = CompiledQuery.Compile((Linq2Sql.DataClassesDataContext ctx, int id) => ctx.Posts.First(p => p.Id == id));
  118. tests.Add(id => compiledGetPost(l2scontext2, id), "Linq2Sql: Compiled");
  119. var l2scontext3 = GetL2SContext(connection);
  120. tests.Add(id => l2scontext3.ExecuteQuery<Post>("select * from Posts where Id = {0}", id).First(), "Linq2Sql: ExecuteQuery");
  121. }, "LINQ-to-SQL");
  122. // Entity Framework
  123. Try(() =>
  124. {
  125. var entityContext = new EFContext(connection);
  126. tests.Add(id => entityContext.Posts.First(p => p.Id == id), "Entity Framework");
  127. var entityContext2 = new EFContext(connection);
  128. tests.Add(id => entityContext2.Database.SqlQuery<Post>("select * from Posts where Id = {0}", id).First(), "Entity Framework: SqlQuery");
  129. var entityContext3 = new EFContext(connection);
  130. tests.Add(id => entityContext3.Posts.AsNoTracking().First(p => p.Id == id), "Entity Framework: No Tracking");
  131. }, "Entity Framework");
  132. // Entity Framework Core
  133. Try(() =>
  134. {
  135. var entityContext = new EFCoreContext(ConnectionString);
  136. tests.Add(id => entityContext.Posts.First(p => p.Id == id), "Entity Framework Core");
  137. var entityContext2 = new EFCoreContext(ConnectionString);
  138. tests.Add(id => entityContext2.Posts.FromSql("select * from Posts where Id = {0}", id).First(), "Entity Framework Core: FromSql");
  139. var entityContext3 = new EFContext(connection);
  140. tests.Add(id => entityContext3.Posts.AsNoTracking().First(p => p.Id == id), "Entity Framework Core: No Tracking");
  141. }, "Entity Framework Core");
  142. // Dapper
  143. Try(() =>
  144. {
  145. var mapperConnection = GetOpenConnection();
  146. tests.Add(id => mapperConnection.Query<Post>("select * from Posts where Id = @Id", new { Id = id }, buffered: true).First(), "Dapper: Query (buffered)");
  147. tests.Add(id => mapperConnection.Query<Post>("select * from Posts where Id = @Id", new { Id = id }, buffered: false).First(), "Dapper: Query (non-buffered)");
  148. tests.Add(id => mapperConnection.QueryFirstOrDefault<Post>("select * from Posts where Id = @Id", new { Id = id }), "Dapper: QueryFirstOrDefault");
  149. var mapperConnection2 = GetOpenConnection();
  150. tests.Add(id => mapperConnection2.Query("select * from Posts where Id = @Id", new { Id = id }, buffered: true).First(), "Dapper: Dynamic Query (buffered)");
  151. tests.Add(id => mapperConnection2.Query("select * from Posts where Id = @Id", new { Id = id }, buffered: false).First(), "Dapper: Dynamic Query (non-buffered)");
  152. tests.Add(id => mapperConnection2.QueryFirstOrDefault("select * from Posts where Id = @Id", new { Id = id }), "Dapper: Dynamic QueryFirstOrDefault");
  153. // dapper.contrib
  154. var mapperConnection3 = GetOpenConnection();
  155. tests.Add(id => mapperConnection3.Get<Post>(id), "Dapper.Contrib");
  156. }, "Dapper");
  157. // Massive
  158. Try(() =>
  159. {
  160. var massiveModel = new DynamicModel(ConnectionString);
  161. var massiveConnection = GetOpenConnection();
  162. tests.Add(id => massiveModel.Query("select * from Posts where Id = @0", massiveConnection, id).First(), "Massive: Dynamic ORM Query");
  163. }, "Massive");
  164. // PetaPoco
  165. Try(() =>
  166. {
  167. // PetaPoco test with all default options
  168. var petapoco = new PetaPoco.Database(ConnectionString, "System.Data.SqlClient");
  169. petapoco.OpenSharedConnection();
  170. tests.Add(id => petapoco.Fetch<Post>("SELECT * from Posts where Id=@0", id).First(), "PetaPoco: Normal");
  171. // PetaPoco with some "smart" functionality disabled
  172. var petapocoFast = new PetaPoco.Database(ConnectionString, "System.Data.SqlClient");
  173. petapocoFast.OpenSharedConnection();
  174. petapocoFast.EnableAutoSelect = false;
  175. petapocoFast.EnableNamedParams = false;
  176. petapocoFast.ForceDateTimesToUtc = false;
  177. tests.Add(id => petapocoFast.Fetch<Post>("SELECT * from Posts where Id=@0", id).First(), "PetaPoco: Fast");
  178. }, "PetaPoco");
  179. // NHibernate
  180. Try(() =>
  181. {
  182. var nhSession1 = NHibernateHelper.OpenSession();
  183. tests.Add(id => nhSession1.CreateSQLQuery("select * from Posts where Id = :id")
  184. .SetInt32("id", id)
  185. .List(), "NHibernate: SQL");
  186. var nhSession2 = NHibernateHelper.OpenSession();
  187. tests.Add(id => nhSession2.CreateQuery("from Post as p where p.Id = :id")
  188. .SetInt32("id", id)
  189. .List(), "NHibernate: HQL");
  190. var nhSession3 = NHibernateHelper.OpenSession();
  191. tests.Add(id => nhSession3.CreateCriteria<Post>()
  192. .Add(Restrictions.IdEq(id))
  193. .List(), "NHibernate: Criteria");
  194. var nhSession4 = NHibernateHelper.OpenSession();
  195. tests.Add(id => nhSession4
  196. .Query<Post>()
  197. .First(p => p.Id == id), "NHibernate: LINQ");
  198. var nhSession5 = NHibernateHelper.OpenSession();
  199. tests.Add(id => nhSession5.Get<Post>(id), "NHibernate: Session.Get");
  200. }, "NHibernate");
  201. // Simple.Data
  202. Try(() =>
  203. {
  204. var sdb = Simple.Data.Database.OpenConnection(ConnectionString);
  205. tests.Add(id => sdb.Posts.FindById(id).FirstOrDefault(), "Simple.Data");
  206. }, "Simple.Data");
  207. // Belgrade
  208. Try(() =>
  209. {
  210. var query = new Belgrade.SqlClient.SqlDb.QueryMapper(ConnectionString);
  211. tests.AsyncAdd(id => query.ExecuteReader("SELECT TOP 1 * FROM Posts WHERE Id = " + id,
  212. reader =>
  213. {
  214. var post = new Post();
  215. post.Id = reader.GetInt32(0);
  216. post.Text = reader.GetString(1);
  217. post.CreationDate = reader.GetDateTime(2);
  218. post.LastChangeDate = reader.GetDateTime(3);
  219. post.Counter1 = reader.IsDBNull(4) ? null : (int?)reader.GetInt32(4);
  220. post.Counter2 = reader.IsDBNull(5) ? null : (int?)reader.GetInt32(5);
  221. post.Counter3 = reader.IsDBNull(6) ? null : (int?)reader.GetInt32(6);
  222. post.Counter4 = reader.IsDBNull(7) ? null : (int?)reader.GetInt32(7);
  223. post.Counter5 = reader.IsDBNull(8) ? null : (int?)reader.GetInt32(8);
  224. post.Counter6 = reader.IsDBNull(9) ? null : (int?)reader.GetInt32(9);
  225. post.Counter7 = reader.IsDBNull(10) ? null : (int?)reader.GetInt32(10);
  226. post.Counter8 = reader.IsDBNull(11) ? null : (int?)reader.GetInt32(11);
  227. post.Counter9 = reader.IsDBNull(12) ? null : (int?)reader.GetInt32(12);
  228. }), "Belgrade Sql Client");
  229. }, "Belgrade Sql Client");
  230. //Susanoo
  231. Try(() =>
  232. {
  233. var susanooDb = new DatabaseManager(connection);
  234. var susanooPreDefinedCommand =
  235. CommandManager.Instance.DefineCommand("SELECT * FROM Posts WHERE Id = @Id", CommandType.Text)
  236. .DefineResults<Post>()
  237. .Realize();
  238. var susanooDynamicPreDefinedCommand =
  239. CommandManager.Instance.DefineCommand("SELECT * FROM Posts WHERE Id = @Id", CommandType.Text)
  240. .DefineResults<dynamic>()
  241. .Realize();
  242. tests.Add(Id =>
  243. CommandManager.Instance.DefineCommand("SELECT * FROM Posts WHERE Id = @Id", CommandType.Text)
  244. .DefineResults<Post>()
  245. .Realize()
  246. .Execute(susanooDb, new { Id }).First(), "Susanoo: Mapping Cache Retrieval");
  247. tests.Add(Id =>
  248. CommandManager.Instance.DefineCommand("SELECT * FROM Posts WHERE Id = @Id", CommandType.Text)
  249. .DefineResults<dynamic>()
  250. .Realize()
  251. .Execute(susanooDb, new { Id }).First(), "Susanoo: Dynamic Mapping Cache Retrieval");
  252. tests.Add(Id => susanooDynamicPreDefinedCommand
  253. .Execute(susanooDb, new { Id }).First(), "Susanoo: Dynamic Mapping Static");
  254. tests.Add(Id => susanooPreDefinedCommand
  255. .Execute(susanooDb, new { Id }).First(), "Susanoo: Mapping Static");
  256. }, "Susanoo");
  257. //ServiceStack's OrmLite:
  258. Try(() =>
  259. {
  260. var dbFactory = new OrmLiteConnectionFactory(ConnectionString, SqlServerDialect.Provider);
  261. var db = dbFactory.Open();
  262. tests.Add(id => db.SingleById<Post>(id), "ServiceStack.OrmLite: SingleById");
  263. }, "ServiceStack.OrmLite");
  264. // Hand Coded
  265. Try(() =>
  266. {
  267. var postCommand = new SqlCommand()
  268. {
  269. Connection = connection,
  270. CommandText = @"select Id, [Text], [CreationDate], LastChangeDate,
  271. Counter1,Counter2,Counter3,Counter4,Counter5,Counter6,Counter7,Counter8,Counter9 from Posts where Id = @Id"
  272. };
  273. var idParam = postCommand.Parameters.Add("@Id", SqlDbType.Int);
  274. tests.Add(id =>
  275. {
  276. idParam.Value = id;
  277. using (var reader = postCommand.ExecuteReader())
  278. {
  279. reader.Read();
  280. var post = new Post();
  281. post.Id = reader.GetInt32(0);
  282. post.Text = reader.GetNullableString(1);
  283. post.CreationDate = reader.GetDateTime(2);
  284. post.LastChangeDate = reader.GetDateTime(3);
  285. post.Counter1 = reader.GetNullableValue<int>(4);
  286. post.Counter2 = reader.GetNullableValue<int>(5);
  287. post.Counter3 = reader.GetNullableValue<int>(6);
  288. post.Counter4 = reader.GetNullableValue<int>(7);
  289. post.Counter5 = reader.GetNullableValue<int>(8);
  290. post.Counter6 = reader.GetNullableValue<int>(9);
  291. post.Counter7 = reader.GetNullableValue<int>(10);
  292. post.Counter8 = reader.GetNullableValue<int>(11);
  293. post.Counter9 = reader.GetNullableValue<int>(12);
  294. }
  295. }, "Hand Coded");
  296. #if !NETSTANDARD1_3
  297. var table = new DataTable
  298. {
  299. Columns =
  300. {
  301. {"Id", typeof (int)},
  302. {"Text", typeof (string)},
  303. {"CreationDate", typeof (DateTime)},
  304. {"LastChangeDate", typeof (DateTime)},
  305. {"Counter1", typeof (int)},
  306. {"Counter2", typeof (int)},
  307. {"Counter3", typeof (int)},
  308. {"Counter4", typeof (int)},
  309. {"Counter5", typeof (int)},
  310. {"Counter6", typeof (int)},
  311. {"Counter7", typeof (int)},
  312. {"Counter8", typeof (int)},
  313. {"Counter9", typeof (int)},
  314. }
  315. };
  316. tests.Add(id =>
  317. {
  318. idParam.Value = id;
  319. object[] values = new object[13];
  320. using (var reader = postCommand.ExecuteReader())
  321. {
  322. reader.Read();
  323. reader.GetValues(values);
  324. table.Rows.Add(values);
  325. }
  326. }, "DataTable via IDataReader.GetValues");
  327. #endif
  328. }, "Hand Coded");
  329. // Subsonic isn't maintained anymore - doesn't import correctly
  330. //Try(() =>
  331. // {
  332. // // Subsonic ActiveRecord
  333. // tests.Add(id => 3SubSonic.Post.SingleOrDefault(x => x.Id == id), "SubSonic ActiveRecord.SingleOrDefault");
  334. // // Subsonic coding horror
  335. // SubSonic.tempdbDB db = new SubSonic.tempdbDB();
  336. // tests.Add(id => new SubSonic.Query.CodingHorror(db.Provider, "select * from Posts where Id = @0", id).ExecuteTypedList<Post>(), "SubSonic Coding Horror");
  337. //}, "Subsonic");
  338. //// BLToolkit - doesn't import correctly in the new .csproj world
  339. //var db1 = new DbManager(GetOpenConnection());
  340. //tests.Add(id => db1.SetCommand("select * from Posts where Id = @id", db1.Parameter("id", id)).ExecuteList<Post>(), "BLToolkit");
  341. Console.WriteLine();
  342. Console.WriteLine("Running...");
  343. await tests.RunAsync(iterations).ConfigureAwait(false);
  344. #pragma warning restore RCS1121 // Use [] instead of calling 'First'.
  345. #pragma warning restore IDE0017 // Simplify object initialization
  346. }
  347. }
  348. }
  349. }