对不同的模型使用相同的dbcontext

时间:2012-04-06 18:02:31

标签: entity-framework code-first

我有一个空的DbContext。映射是动态创建的,DbContext通常使用Set();

以下是我的通用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字段的对象。

我的问题是,当我第二次使用MethodObjectContext new()并进行查询时,不会调用ModelCreating方法,导致我得到以下错误。

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

Product2将是调用ModelCreating事件的上下文的一部分,但事实并非如此。有什么想法吗?

注意:我期待错误,因为我们使用相同的连接字符串(sdf)并且正在创建的数据库没有创建我的第二个调用(Product2)所需的附加字段。

1 个答案:

答案 0 :(得分: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);
}