我有一个继承自抽象基类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);
}
}
我在数据库中看到的查询是两个常见的迁移查询......
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
有关如何阻止Entity Framework进行这些查询的任何想法?
答案 0 :(得分:12)
您需要在静态构造函数中执行此操作,或者更好地在实例化Context之前执行此操作。
static MyDbContext() {
Database.SetInitializer<MyDbContext>(null);
}
答案 1 :(得分:9)
很抱歉回答这么老的问题,特别是那个被标记为已回答的问题,但它一直困扰着我,我想提供解决方案。
问题是LINQPad创建了DbContext类的子类。因此,当您调用Database.SetInitializer<MyDbContext>(null)
时,只要您创建MyDbContext的实例,它就会起作用。但是按照设计,LINQPad会将您的代码编译成一个派生自MyDbContext的类。如果你使MyDbContext密封,LINQPad将无法使用它。
解决方法是使用反射在MyDbContext的实例构造函数中调用Database.SetInitializer
。这意味着你不必为每个上下文实例调用它,但它不会伤害任何东西。但是这允许你使用this.GetType()来访问LINQPad创建的子类,然后你可以使用反射来调用SetInitializer
。
如果添加了非泛型版本的方法,那会很好。
This Gist has an example使用反射来调用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 } );