2012-04-06 74 views
0

我有一個空的DbContext。映射是動態創建的,而DbContext通常使用Set();對不同的模型使用相同的dbcontext

以下是我的通用DbContext。

/// <summary> 
/// Object context 
/// </summary> 
public class MethodObjectContext : DbContext, IDbContext 
{ 
    private readonly IEventPublisher _eventPublisher; 

    public MethodObjectContext(string nameOrConnectionString, IEventPublisher eventPublisher) 
     : base(nameOrConnectionString) 
    { 
     _eventPublisher = eventPublisher; 
    } 

    public MethodObjectContext(DbConnection existingConnection, bool contextOwnsConnection, IEventPublisher eventPublisher) 
     : base(existingConnection, contextOwnsConnection) 
    { 
     _eventPublisher = eventPublisher; 
    } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     _eventPublisher.Publish(new ModelCreating(modelBuilder)); 
     base.OnModelCreating(modelBuilder); 
    } 

    public new IDbSet<TEntity> Set<TEntity>() where TEntity : class 
    { 
     return base.Set<TEntity>(); 
    } 
} 

我試圖寫一個單元測試,將斷言該數據庫是不同步的,如果我改變映射(從ModelCreating事件)。

以下是我的測試代碼。

[TestClass] 
public class MigrationTests 
{ 
    private string _connectionString = string.Empty; 
    private string _testDb = string.Empty; 

    public MigrationTests() 
    { 
     _testDb = Path.Combine("C:\\", System.Reflection.Assembly.GetExecutingAssembly().GetName().Name.Replace(".", "") + ".sdf"); 

     if (File.Exists(_testDb)) 
      File.Delete(_testDb); 

     _connectionString = string.Format("Data Source={0};Persist Security Info=False;", _testDb); 

     Database.DefaultConnectionFactory = new SqlCeConnectionFactory("System.Data.SqlServerCe.4.0"); 
    } 

    [TestMethod] 
    public void ThrowsErrorForOutOfDateDatabase() 
    { 
     // The initializer will handle migrating the database. 
     // If ctor param is false, auto migration is off and an error will be throw saying the database is out of date. 
     Database.SetInitializer(new MigrationDatabaseInitializer<MethodObjectContext>(false)); 

     // Create the initial database and do a query. 
     // This will create the database with the conventions of the Product1 type. 
     TryQueryType<Product1>("Product"); 

     // The next query will create a new model that has conventions for the product2 type. 
     // It has an additional property which makes the database (created from previous query) out of date. 
     // An error should be thrown indicating that the database is out of sync. 
     ExceptionAssert.Throws<InvalidOperationException>(() => TryQueryType<Product2>("Product")); 
    } 

    private void TryQueryType<T>(string tableName) where T : class 
    { 
     using (var context = new MethodObjectContext(_connectionString, new FakeEventPublisher(x => x.ModelBuilder.Entity<T>().ToTable(tableName)))) 
     { 
      var respository = new EfRepository<T>(context); 
      var items = respository.Table.ToList(); 
     } 
    } 
} 

我的Product1類是一個POCO對象,而我的Product2類是具有額外的db字段的同一個對象。

我的問題是,當我new()第二次Method.comContext並做一個查詢,ModelCreating方法不會被調用,導致我得到以下錯誤。

The entity type Product2 is not part of the model for the current context. 

Product2將被調用的ModelCreating事件的上下文的一部分,但事實並非如此。有任何想法嗎?

注意:由於我們使用相同的連接字符串(sdf),並且創建的數據庫未創建第二個調用(Product2)所需的附加字段,所以我期待錯誤。

回答

0

我的DbCompiledModel被緩存。以下刷新緩存。

private void ClearDbCompiledModelCache() 
{ 
    var type = Type.GetType("System.Data.Entity.Internal.LazyInternalContext, EntityFramework"); 
    var cmField = type.GetField("CachedModels",System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic); 
    var cachedModels = cmField.GetValue(null); 
    cachedModels.GetType().InvokeMember("Clear", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.InvokeMethod, null, cachedModels, null); 
} 
+3

請注意,緩存是有原因的。構建模型可能很昂貴,如果每次使用上下文時都會執行該模型,那麼應用程序可能會出現性能問題。更好的方法是直接使用DbModelBuilder創建DbCompiledModels,然後根據需要進行緩存。 DbContext具有接受DbCompiledModel的構造函數。 – 2012-04-07 23:02:17

相關問題