SQL Server 2005的Code First?

3

我的开发数据库是2008 R2,Code First使用DropCreateIfModelChanges生成本地数据库。

我的生产部署方法是从本地DB生成脚本,包括数据,并在生产环境中运行。这将创建所有表,包括EdmMetadata表,并用哈希值填充它。

有效的方法:

在不同的2008 R2实例中运行脚本,将Entity模型的连接字符串更改为指向此生产实例,运行应用程序。

无效的方法:

在不同的2005实例中运行脚本,将Entity模型的连接字符串更改为指向此生产实例,运行应用程序。我会收到一个错误,指示模型已更改。

我认为这不起作用是因为DB兼容性版本是哈希的一部分。因此,在生产中,它会生成一个哈希并将其与存储在EdmMetadata表中的哈希进行比较。新哈希不同,因为它是针对2005 DB生成的。

我猜如果我在本地生成一个2005 DB并将其部署到2005生产实例中,则不会出现此问题。但是,我没有安装2005,而且也不想要求所有开发人员都安装它,因为2008已经支持2005兼容模式。

如何强制EF在2005兼容模式下生成DB?


你尝试过直接从PM控制台创建脚本吗?即“Update-Database –Script” - 这是迁移功能的一部分(谈论4.3)。然后手动执行。整个迁移部分就是为这样的事情而设计的,我现在不确定也无法测试,但我认为你应该遵循推荐路线,在生成Db之前使用迁移(和/或脚本),那么你就不会有问题。如果你正在使用默认的“SqlConnectionFactory”,那应该没问题,可以工作。 - NSGaga-mostly-inactive
1个回答

2
如果唯一的问题是模型兼容性检查,那么在生产环境中运行时,您可以禁用上下文的数据库初始化器,因为您可能不需要初始化数据库。您可以通过以下代码来实现这一点:
Database.SetInitializer<MyContext>(null);

但是在生产应用中,最好在app.config/web.config中进行配置,如下所示:
<entityFramework>
  <contexts>
    <context type="MyNamespace.MyContext, MyAssembly" disableDatabaseInitialization="true" />
  </contexts>
</entityFramework>

您需要更新到EF 4.3才能使用这个语法--请参见http://blogs.msdn.com/b/adonet/archive/2012/01/12/ef-4-3-configuration-file-settings.aspx。在EF 4.1中也有一种方法:请参见http://blog.oneunicorn.com/2011/03/31/configuring-database-initializers-in-a-config-file/
您也可以尝试直接升级到EF 4.3,它不再使用EdmMetadata表,而是使用__MigrationHistory表。这种方式以不同的方式检查模型兼容性。如果Code First为2005生成的数据库与为2008生成的数据库不同,它仍然可能会标记出差异,这种情况偶尔会发生。
您可以在开发机上安装SQL Server 2005 Express。它是免费的,可以更好地匹配您的生产环境。
最后,如果以上方法都不起作用,你需要强制Code First生成一个2005的模型/数据库,那么你可以这样做,但这意味着使用更低级别的构建块。首先,你需要自己创建DbModelBuilder并为上下文中声明了DbSet的每个实体类型调用Entity方法:
var modelBuilder = new DbModelBuilder();
modelBuilder.Entity<User>();
modelBuilder.Entity<Blog>();

您可以在此处进行其他流畅的配置,或像往常一样使用数据注释。不会调用OnModelCreating,所以不要在那里放置流畅的调用-而是将它们移到这里。
一旦您有一个配置好的DbModelBuilder,您需要构建和编译才能获得一个编译后的模型,该模型可以传递给DbContext。在这个阶段,您可以将“2005”作为提供程序清单标记传递进去。
var compiledModel = modelBuilder
    .Build(new DbProviderInfo("System.Data.SqlClient", "2005"))
    .Compile();

现在你应该将这个已编译的模型缓存到你的应用程序域中,这样你只需要构建和编译一次。 (通常情况下,DbContext 在构建模型时会自动进行缓存,但如果你需要自己构建模型,那么你也需要自己进行缓存。)
最后,你需要每次使用时将编译好的模型传递给上下文的一个构造函数,并让该构造函数将模型传递给基类构造函数。
public class MyContext : DbContext
{
    public MyContext(DbCompiledModel model)
        : base(model)
    {
    }

    public DbSet<User> Users { get; set; }
    public DbSet<Blog> Blogs { get; set; }
}

如果需要的话,还有其他构造函数重载可以传递名称或连接字符串。

+1 谢谢,我下次部署时会尝试这个方法。我喜欢在配置文件中进行操作的想法,因为我可以将其放在 web.Production.config 转换中,专门针对生产构建/部署配置。 - AaronLS

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接