Skip to content

Instantly share code, notes, and snippets.

@davepcallan
Created February 10, 2025 21:42
Show Gist options
  • Save davepcallan/592f4feb18b9e9cfd8f0e27738a596e5 to your computer and use it in GitHub Desktop.
Save davepcallan/592f4feb18b9e9cfd8f0e27738a596e5 to your computer and use it in GitHub Desktop.
Benchmarking different ways of calculating average of a column in Entity Framework
using System;
using System.Linq;
using BenchmarkDotNet.Attributes;
using Microsoft.EntityFrameworkCore;
[MemoryDiagnoser]
[ReturnValueValidator]
public class AverageBlogRanking
{
[Params(1000)]
public int NumBlogs; // number of records to write [once], and read [each pass]
[GlobalSetup]
public void Setup()
{
using var context = new BloggingContext();
context.Database.EnsureDeleted();
context.Database.EnsureCreated();
context.SeedData(NumBlogs);
}
[Benchmark]
public double LoadEntitiesNoTracking()
{
var sum = 0;
var count = 0;
using var ctx = new BloggingContext();
foreach (var blog in ctx.Blogs.AsNoTracking())
{
sum += blog.Rating;
count++;
}
return (double)sum / count;
}
[Benchmark]
public double ProjectOnlyRanking()
{
var sum = 0;
var count = 0;
using var ctx = new BloggingContext();
foreach (var rating in ctx.Blogs.Select(b => b.Rating))
{
sum += rating;
count++;
}
return (double)sum / count;
}
[Benchmark(Baseline = true)]
public double CalculateInDatabase()
{
using var ctx = new BloggingContext();
return ctx.Blogs.Average(b => b.Rating);
}
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.UseSqlServer(@"Server=localhost;Database=Blogging;Trusted_Connection=True;TrustServerCertificate=true");
public void SeedData(int numblogs)
{
Blogs.AddRange(
Enumerable.Range(0, numblogs).Select(
i => new Blog
{
Name = $"Blog{i}",
Url = $"blog{i}.blogs.net",
CreationTime = new DateTime(2020, 1, 1),
Rating = i % 5
}));
SaveChanges();
}
}
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public DateTime CreationTime { get; set; }
public int Rating { get; set; }
}
}
public class Program
{
public static void Main(string[] args)
{
BenchmarkRunner.Run<AverageBlogRanking>();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment