通过ObjectContext脚本化EF 4.3代码优先数据库失败,而通过内置DatabaseInitializer创建成功

时间:2012-05-31 20:04:31

标签: entity-framework entity-framework-4.3

我想以编程方式为我的EF 4.3 Code-First数据库创建数据库创建脚本。使用标准的DatabaseInitializer机制创建数据库就好了,但是下面的代码失败了:

using(var dc = new MyContext())
{
    var objContext = (IObjectContextAdapter)dc;
    var script = objContext.ObjectContext.CreateDatabaseScript();
}

我得到的例外是:

  

不属于'timestamp'或'rowversion'类型的属性不支持商店生成的模式'Computed'。

我确实有一个类型为“string”的Computed列,但就像我说的那样,数据库在通过内置的DatabaseInitializer创建时创建得很好。奇怪的是,使用此方法生成的模式实际上并不创建计算列。

至于为什么我这样做,我有一个运行后创建的脚本,它会删除此列并创建一个真实的计算列。如果不指定在EF映射中计算的列,它将尝试在插入时为该列分配值,然后失败。

1 个答案:

答案 0 :(得分:1)

暂时搁置数据库创建,设置“Computed”意味着EF不会尝试写入该列的值,但会在每次查询列时读取服务器(可能是)计算机的值。从EF的角度来看,为任何数据类型都有一个计算列是有效的。

现在考虑从EF模型创建数据库。 EF不知道如何在数据库中创建计算列,实际上,根据列的类型,在某些数据库中没有触发器甚至可能无法执行此操作。因此,在EF4中,决定在这些情况下使CreateDatabaseScript抛出。

但是,在针对SQL Server或SQL Server Compact时,EF 4.3及更高版本不再使用CreateDatabaseScript。他们改为使用迁移管道。对于迁移管道,我们决定采用不同的方法,因为我们认为数据库创建总是抛出可能是完全有效的模型是错误的。特别是考虑到您可以在迁移中编写自己的SQL,这些迁移添加了触发器或其他一些机制来使数据库创建有效的计算列。

因此,这就是为什么您看到数据库是由EF 4.3创建的(但没有做任何事情来使列计算),但是当您尝试使用使用较旧的非迁移机制的CreateDatabaseScript时,您会看到相同的模型抛出。

解决此问题的方法是让迁移创建脚本而不是使用CreateDatabaseScript。