我们有一个自定义初始化程序,它不会以任何方式更改数据库模式;它所做的就是播种一些数据。 我被要求提出一个自定义初始化程序,它将始终删除数据库,然后使用相同的种子数据填充它(这将仅在我们的数据库测试项目中使用)。
我写过这个初始化程序:
public class DropAndSeedDbInitializer<TContext, TSeedDataInitializer> : IDatabaseInitializer<TContext>
where TContext : DbContext
where TSeedDataInitializer : IDatabaseInitializer<TContext>, new()
{
private readonly DropCreateDatabaseAlways<TContext> _dbInitializer;
private readonly IDatabaseInitializer<TContext> _seedDataInitializer;
public DropAndSeedDbInitializer()
{
_dbInitializer = new DropCreateDatabaseAlways<TContext>();
_seedDataInitializer = Activator.CreateInstance<TSeedDataInitializer>();
}
public void InitializeDatabase(TContext context)
{
context.Database.ExecuteSqlCommand(TransactionalBehavior.DoNotEnsureTransaction
, string.Format("ALTER DATABASE [{0}] SET SINGLE_USER WITH ROLLBACK IMMEDIATE", context.Database.Connection.Database));
_dbInitializer.InitializeDatabase(context);
_seedDataInitializer.InitializeDatabase(context);
}
}
我打电话时工作正常
LicenceContext context = new LicenceContext();
Database.SetInitializer(new DropAndSeedDbInitializer<LicenceContext, TestSeedDataInitializer>());
context.Database.Initialize(true);
然后我决定在app.config中配置它,如下所示:
<context type="Foo.LicenceContext, MyAssembly">
<databaseInitializer
type="Foo.DropAndSeedDbInitializer`2[[Foo.LicenceContext, MyAssembly], Foo.TestSeedDataInitializer, MyAssembly]], MyAssembly" />
</context>
我删除了这段代码:
Database.SetInitializer(new DropAndSeedDbInitializer<LicenceContext, TestSeedDataInitializer>());
context.Database.Initialize(true);
但是当我第一次尝试访问我的上下文时,我得到了这个错误:
Failed to set database initializer of type 'Foo.DropAndSeedDbInitializer`2[[Foo.LicenceContext, MyAssembly], Foo.TestSeedDataInitializer, MyAssembly]], MyAssembly' for DbContext type 'Foo.LicenceContext, MyAssembly' specified in the application configuration. See inner exception for details.
内部例外是:
Exception of type 'System.ArgumentException' was thrown.
Parameter name: typeName@149
at System.Data.Entity.Internal.InitializerConfig.TryGetInitializer(Type requiredContextType, String contextTypeName, String initializerTypeName, Boolean isDisabled, Func`1 initializerArgs, Func`3 exceptionMessage)
at System.Data.Entity.Internal.InitializerConfig.<>c__DisplayClass6.<TryGetInitializerFromEntityFrameworkSection>b__1(ContextElement e)
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source, Func`2 predicate)
at System.Data.Entity.Internal.InitializerConfig.TryGetInitializerFromEntityFrameworkSection(Type contextType)
at System.Data.Entity.Internal.InitializerConfig.TryGetInitializer(Type contextType)
at System.Data.Entity.Infrastructure.DependencyResolution.AppConfigDependencyResolver.GetServiceFactory(Type type, String name)
at System.Data.Entity.Infrastructure.DependencyResolution.AppConfigDependencyResolver.<>c__DisplayClass1.<GetService>b__0(Tuple`2 t)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at System.Data.Entity.Infrastructure.DependencyResolution.AppConfigDependencyResolver.GetService(Type type, Object key)
at System.Data.Entity.Infrastructure.DependencyResolution.ResolverChain.<>c__DisplayClass3.<GetService>b__0(IDbDependencyResolver r)
at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
然后我创建了一个继承自DropAndSeedDbInitializer的类,如下所示:
public class DummyInitializer : DropAndSeedDbInitializer<LicenceContext, TestSeedDataInitializer>
{
}
我在app.config中配置了它,如下所示:
<context type="Foo.LicenceContext, MyAssembly">
<databaseInitializer
type="Foo.DummyInitializer, MyAssembly" />
</context>
然后DropAndSeedDbInitalizer运行,我可以毫无问题地访问我的上下文。
所以我的问题是:我应该能够在app.config中配置这个自定义初始化程序吗?如果我应该,我做错了什么?
谢谢,
大卫