4

I have a context class that inherits from an abstract base AuditableDbContext : DbContext. The AuditableDbContext takes two parameters, one for the auditor and one for the context to audit into.

In the inherited class, I have a default parameterless constructor that calls the other constructors with null parameters and then in the final constructor I call Database.SetInitializer<MyDbContext>(null) after calling the base constructor.

The problem is that even when I do this, I still get the db migration calls on the database server when the application starts.

public abstract class AuditableContext : DbContext
{
  public AuditableContext(IAuditor auditor, DbContext auditContext)
  {
    // params can be null resulting in no auditing
    // initialization stuff here...
  }
}

public class MyDbContext : AuditableContext
{
  // DbSets here...

  public MyDbContext() : this(null, null) {}

  public MyDbContext(IAuditor auditor) : this(auditor, null) {}

  public MyDbContext(IAuditor auditor, DbContext auditContext) 
  : base(auditor, auditContext)
  {
    Database.SetInitializer<MyDbContext>(null);
  }
}

The queries I see on the database are the two common migration queries...

SELECT [GroupBy1].[A1] AS [C1]
FROM ( SELECT COUNT(1) AS [A1]
FROM [dbo].[__MigrationHistory] AS [Extent1]
)  AS [GroupBy1]

SELECT TOP (1) 
[Extent1].[Id] AS [Id], 
[Extent1].[ModelHash] AS [ModelHash]
FROM [dbo].[EdmMetadata] AS [Extent1]
ORDER BY [Extent1].[Id] DESC

Any ideas on how to stop Entity Framework from making these queries?

GoClimbColorado
  • 1,060
  • 3
  • 13
  • 28

2 Answers2

12

You will need to do this in the static constructor or better still PRIOR to instantiating the Context.

static MyDbContext() {
    Database.SetInitializer<MyDbContext>(null);
}
phil soady
  • 11,043
  • 5
  • 50
  • 95
  • Thanks... I found this [edmmetadata link](http://bit.ly/wcwP8E) too. Still LinqPad insists on running the initializer queries... Any idea on that? – GoClimbColorado May 24 '13 at 05:04
  • the static "Database" was intended to be used before access to the context. I stick to that. So sorry no further suggestions. – phil soady May 24 '13 at 05:09
  • There is also a sample in EF6 code on managing the migration and dbContext constructors here. http://stackoverflow.com/a/16133150/1347784 – phil soady Sep 27 '13 at 01:39
9

Sorry to reply to such an old question, especially one that is marked as answered, but it has plagued me and I wanted to offer a solution regardless.

The problem is that LINQPad creates a subclass of your DbContext class. So when you called Database.SetInitializer<MyDbContext>(null), that will work as long as you are creating an instance of MyDbContext. But by design, LINQPad compiles your code into a class that derives from MyDbContext. If you make MyDbContext sealed, LINQPad won't be able to use it.

The workaround is to use reflection to call Database.SetInitializer in the instance constructor of MyDbContext. This means you're unnecessarily calling it for every instance of the context, but it won't hurt anything. But this allows you to use this.GetType() to get access to the subclass that LINQPad creates and then you can use reflection to call SetInitializer.

Would be nice if a non-generic version of the method was added though.

This Gist has an example of using reflection to call Database.SetInitializer.

var databaseType = typeof( Database );
var setInitializer = databaseType.GetMethod( "SetInitializer", BindingFlags.Static | BindingFlags.Public );

var thisType = GetType( );
var setInitializerT = setInitializer.MakeGenericMethod( thisType );

setInitializerT.Invoke( null, new object[] { null } );
Josh
  • 68,005
  • 14
  • 144
  • 156
  • perhaps use a second context with Linqpad – phil soady Apr 27 '14 at 03:58
  • 2
    I made an [extension method](https://gist.github.com/kevinkuszyk/06aff7ae95dbbaa2621c) from @Josh's gist which I use in LinqPad. It keeps my DbContext clean. Downside is you have to remember to use it! – Kevin Kuszyk Jul 11 '14 at 15:09