Monthly Archives: September 2018

Unit Testing With Entity Framework and Entity Framework Core 2.1

Entity Framework Core 2.1 comes with a nifty little feature: an In Memory Database setting. What this means, is that with a single option setting, your tests can interact directly with the database (or at least EF’s impression of the database) but not actually touch any physical database. In other words, you can write unit tests for data access; an example:

// Arrange
DbContextOptions<ApplicationDbContext> options = new DbContextOptionsBuilder<ApplicationDbContext>()
    .UseInMemoryDatabase(Guid.NewGuid().ToString())
    .EnableSensitiveDataLogging()                
    .Options;

using (var context = new ApplicationDbContext(options))
{
    context.Database.EnsureDeleted();
	ResourceCategory resourceCategory = new ResourceCategory()
    {
        Name = "TestCategory"
    }
};
 
// Act
_applicationDbContext.ResourceCategories.Add(resourceCategory);
_applicationDbContext.SaveChanges();
	
 
// Assert                
Assert.Equal("TestCategory", context.ResourceCategories.First().Name);               

To just quickly explain what this is doing: we have a DbContext called ApplicationDbContext and we’re building a set of options on top of that context. We’re then instantiating the context and cleaning the in memory database. Finally, we’re adding a new piece of data to the context and then asserting that it has been added.

Told you it was nifty.

But what about if you’re still using Entity Framework 6?

Glad you asked.

Out of the box, EF does not come with this kind of functionality; however, I recently came across (and contributed) to a NuGet library that provides just such a facility. It provides a wrapper for both Moq and Nsubstitute. The GitHub Repo is here.

ReadOnly Entity Framework

Ever come across a situation where you want to use an Entity Framework data layer in a little tool or report, but ended up reverting to Ado.Net or a different ORM because EF is a little bit like a Heisenberg Framework (it changes things that it looks at)? You might have a seed method that tries to update data, or a migration that you don’t want to apply.

Apologies in advance if this seems like stating the bloody obvious; but it didn’t seem obvious to me at the time. If there’s a neater way to do this then please let me know.

Anyway, I recently had this issue, and came up with the idea of a ReadOnly DBContext. For example, your main DBContext might look like this:

    public class MyDbContext : DbContext, IMyDbContext
    {
        static MyDbContext()
        {            
            Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyDbContext, Configuration>());
        }
 
        public MyDbContext()
            : base("connection-string")
        {
            
            
        }
 
        public MyDbContext(string connectionString)
            : base(connectionString)
        {
 
 
        }
 
        public DbSet<Entity1> Entity1 { get; set; }
        public DbSet<Entity2> Entity2 { get; set; }
 
        void IMyDbContext.SaveChanges()
        {
            base.SaveChanges();
        }
 
        Task IMyDbContext.SaveChangesAsync()
        {
            return base.SaveChangesAsync();
        }
 
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Entity1>()
                .HasOptional(a => a.Field2)
                .WithMany();            
  
            base.OnModelCreating(modelBuilder);
        }
    }

Making a ReadOnly version of this is pretty much removing the code; for example:

    public class MyReadOnlyDbContext : DbContext, IMyDbContext
    {
        static MyReadOnlyDbContext()
        {            
            Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyReadOnlyDbContext, Configuration>());
        }
 
        public MyReadOnlyDbContext()
            : base("connection-string")
        {
            
            
        }
 
        public MyReadOnlyDbContext(string connectionString)
            : base(connectionString)
        {
 
 
        }
 
        public DbSet<Entity1> Entity1 { get; set; }
        public DbSet<Entity2> Entity2 { get; set; }
 
        void IMyDbContext.SaveChanges()
        {

        }
 
        Task IMyDbContext.SaveChangesAsync()
        {
		  return Task.CompletedTask;

        }
 
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Entity1>()
                .HasOptional(a => a.Field2)
                .WithMany();
  
            base.OnModelCreating(modelBuilder);
        }
    }

An easy way to return the read only version, rather than the main version is via a DbContextGenerator:

public class DbContextGenerator : IDbContextGenerator
{
    private readonly AppSettings appSettings;        
 
    public DbContextGenerator(AppSettings appSettings)
    {
        this.appSettings = appSettings;            
    }
 
    public IMyDbContext GenerateDbContext()
    {            
        if (appSettings.ReadOnly)
        {
            return new MyDbReadOnlyContext(appSettings.DatabaseConnectionString);
        }
        return new MyDbContext(appSettings.DatabaseConnectionString);                        
    }
}

This can be registered in the IoC and will return a DB Context based on a read only flag.

It’s worth noting that if your model doesn’t match, it will likely crash. It’s also worth noting that if you’re reading this article and trying to work out how you can use EF without having it manage the DB then it’s probably because something, somewhere, went wrong: this isn’t a suggestion for a new way to use EF, it’s a way to use EF in a temporary fashion.