Database.SetInitializer为null无效工作实体框架4.3.1代码优先

GoC*_*ado 4 entity-framework ef-code-first ef-migrations

我有一个继承自抽象基础的上下文类AuditableDbContext : DbContext.在AuditableDbContext有两个参数,一个是审计师和一个用于审计到的上下文.

在继承的类中,我有一个默认的无参数构造函数,它使用null参数调用其他构造函数,然后在Database.SetInitializer<MyDbContext>(null)调用基础构造函数后调用的最终构造函数中.

问题是即使我这样做,我仍然在应用程序启动时在数据库服务器上获得db迁移调用.

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);
  }
}
Run Code Online (Sandbox Code Playgroud)

我在数据库中看到的查询是两个常见的迁移查询...

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
Run Code Online (Sandbox Code Playgroud)

有关如何阻止Entity Framework进行这些查询的任何想法?

phi*_*ady 12

您需要在静态构造函数中执行此操作,或者更好地在实例化Context之前执行此操作.

static MyDbContext() {
    Database.SetInitializer<MyDbContext>(null);
}
Run Code Online (Sandbox Code Playgroud)


Jos*_*osh 9

很抱歉回答这么老的问题,特别是那个被标记为已回答的问题,但它一直困扰着我,我想提供一个解决方案,无论如何.

问题是LINQPad创建了DbContext类的子类.因此,当您调用时Database.SetInitializer<MyDbContext>(null),只要您创建MyDbContext的实例,这将起作用.但是按照设计,LINQPad会将您的代码编译成一个派生自MyDbContext的类.如果密封MyDbContext,LINQPad将无法使用它.

解决方法是使用反射来调用Database.SetInitializerMyDbContext的实例构造函数.这意味着你不必要地为每个上下文实例调用它,但它不会伤害任何东西.但是这允许你使用this.GetType()来访问LINQPad创建的子类,然后你可以使用反射来调用SetInitializer.

如果添加了非泛型版本的方法,那将会很好.

这个要点有一个使用反射来调用的例子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 } );
Run Code Online (Sandbox Code Playgroud)

  • 我从@Josh的gist中制作了[扩展方法](https://gist.github.com/kevinkuszyk/06aff7ae95dbbaa2621c),我在LinqPad中使用了它.它使我的DbContext保持干净.下行是你必须记住使用它! (2认同)