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?

2 Answers 2

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);
}
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks... I found this edmmetadata link too. Still LinqPad insists on running the initializer queries... Any idea on that?
the static "Database" was intended to be used before access to the context. I stick to that. So sorry no further suggestions.
There is also a sample in EF6 code on managing the migration and dbContext constructors here. stackoverflow.com/a/16133150/1347784
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 } );

2 Comments

perhaps use a second context with Linqpad
I made an extension method from @Josh's gist which I use in LinqPad. It keeps my DbContext clean. Downside is you have to remember to use it!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.