假设我有10个实体。其中8个是全新的,并首先使用EF代码进行构建。所以在我使用DropCreateDatabaseIfModelChanges
初始化策略之前,这对我来说非常有效
但现在我有两个实体,它们是基于一些第三方数据从数据库中构建的,我一直需要这些数据,即使模型更改,我也不能允许EF删除这些表。我需要一些更有智慧的东西。
在这种情况下,哪种方法是正确的?
简而言之,我想要一些非常相似的东西。我只需要DbInitializer行为,但要以表为单位,而不是以数据库为单位。我不想让代码优先实体像以前一样工作,正则表达式之类的。但是,只为这两个特定的基于DB的实体添加一些自定义内容。
您可以使用EF代码优先迁移
首先,您需要在PackageManager控制台中运行Enable-Migrations
命令。此命令将向我们的项目中添加一个Migrations文件夹。这个新文件夹包含Configuration
类,该类允许您为上下文配置迁移的行为方式。
现在,在那之后,如果您遵循所需的步骤,您可以从"Package Manager控制台"运行"更新数据库",并将八个新表添加到您的DB:
示例:
- 对模型进行更改(添加八个新实体)
- 从Package Manager控制台:运行添加迁移[迁移名称]
- 对生成的代码进行任何必要的更改(这是可选的)
- 从软件包管理器控制台:运行更新数据库
如果您不更改或删除任何与现有实体相关的属性,就不应该丢失DB中已有的数据。
更新
要实现您想要的目标,您可以使用"自动迁移"。这样,当您运行应用程序时,您将始终获得最新版本的数据库,因为EF将在每次需要时进行隐式迁移-在最纯的版本中,您只需要启用自动迁移即可。
首先,您需要使用新的数据库初始化策略MigrateDatabaseToLatestVersion
在上下文类中设置数据库初始化器,如下所示:
public class YourContext: DbContext
{
public YourContext(): base("DefaultConnectionString")
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<YourContext, YourProject.Migrations.Configuration>("DefaultConnectionString"));
}
}
稍后,在Configuration
类的构造函数中,您必须启用自动迁移:
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
现在,如果您正在使用现有的数据库,在添加新的八个实体之前,您需要首先执行以下操作:
- 在中运行
Add-Migration InitialCreate –IgnoreChanges
命令Package Manager控制台。这将创建一个带有当前模型作为快照 - 在Package Manager控制台中运行
Update-Database
命令。这将对数据库应用InitialCreate迁移。自实际的迁移不包含任何更改,它只会添加一个__MigrationsHistory表的行,指示此迁移已应用
之后,您可以将您想要的更改应用于您的模型(例如,添加新的八个实体),当您再次执行应用程序时,EF将为您进行迁移。
万一你要改变引发数据库不一致的某些操作模式,它可能以数据丢失告终,将抛出异常。如果没有抛出此异常,则不必担心丢失您的数据,它将在您的数据库中保持不变。
作为一种传统信息,如果你不介意丢失数据(我认为这不是你的escenerario,但无论如何都很有用),你可以在true
中设置AutomaticMigrationDataLossAllowed
属性(其默认值为false
),如果你在执行迁移时要丢失数据库中的一些数据,则不会引发异常。
public Configuration()
{
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed=true;
}