PageRenderTime 37ms CodeModel.GetById 2ms app.highlight 27ms RepoModel.GetById 1ms app.codeStats 1ms

/Dapper.Tests.Performance/LegacyTests.cs

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