Tooling with Benchmark.NET – Entity Framework Core vs ADO.NET Part ][ – Multiple Inserts


The previous post (here) left me wondering how slow Entity Framework Core was compared to ADO.NET. This post will be comparing performing 1k record inserts on both libraries. I’ve added the two benchmarks (using Benchmark.Net) to the code. Let’s have a look. (The code can be found here.)

First, I’ll show the additions to the DataAccess.cs class:

        public async Task InsertManyEf(List<string> names)
        {
            var aLst = names.Select(x=> new A() { Name = x });
            await dbContext.ARows.AddRangeAsync(aLst);
            await dbContext.SaveChangesAsync();
        }

        public async Task InsertManyAdo(List<string> names)
        {
            var con = new SqlConnection(EfDbContext.ConnectionString);
            var str = new StringBuilder("INSERT INTO AROWS VALUES");
            var cmd = new SqlCommand();
            cmd.Connection = con;

            for (var i = 0; i < names.Count; i++)
            {
                str.Append($"(@name{i})");
                if(i < names.Count - 1)
                {
                    str.Append(",");
                }

                cmd.Parameters.AddWithValue($"name{i}", names[i]);
            }
            cmd.CommandText = str.ToString();

            try
            {
                con.Open();
                await cmd.ExecuteNonQueryAsync();
            }
            finally
            {
                con.Close();
            }

        }

There are InsertManyEf and InsertManyAdo functions and they do what they say – insert more than one row at a time. Note how much shorter the Entity Framework version is.

Next, let’s look at the new Benchmarks I added:

[Benchmark]
        [ArgumentsSource(nameof(InsertMultipleData))]
        public async Task EntityFrameworkInsertMany(List<string> names)
        {
            var da = new DataAccess();
            await da.InsertManyEf(names);
        }

        [Benchmark]
        [ArgumentsSource(nameof(InsertMultipleData))]
        public async Task AdoInsertMany(List<string> names)
        {
            var da = new DataAccess();
            await da.InsertManyAdo(names);
        }

        public IEnumerable<object> InsertMultipleData()
        {
            yield return Enumerable.Range(0, 1000).Select(x => x.ToString()).ToList();
            yield return Enumerable.Range(1000, 1000).Select(x => x.ToString()).ToList();
            yield return Enumerable.Range(2000, 1000).Select(x => x.ToString()).ToList();
            yield return Enumerable.Range(3000, 1000).Select(x => x.ToString()).ToList();
            yield return Enumerable.Range(4000, 1000).Select(x => x.ToString()).ToList();
        }

There are two functions that insert data using the new Entity Framework and ADO insert functions. The InsertMultipleData function is the source for the inserts. It simply uses numbers (Range) as strings that are used as the names for the inserts and since there are four yields, the results will contain four results for each benchmark. Let’s run just these two benchmarks and see the results:

As you can see, the Entity Framework inserts take roughly 3.5 times longer and use about 20 times more memory. It is a bit surprising but good to know. If you need to bulk insert a bunch of rows into SQL then use ADO.NET!

Thanks for stopping by!

, ,