EF6 – 运行没有种子的Update-Database命令

我正在使用entity framework6,我正在使用迁移。 我已经使用初始迁移创建了数据库。 现在我已对模型进行了更改,并且上下文已更改,我想更新数据库但是…当我再次尝试运行Database-Update命令时,种子也在运行,这会因为某些数据而导致错误再次插入。

那么,如何在不运行种子方法的情况下运行Update-Database命令?


很难相信EF没有像-No-Seed这样的简单选项。 其他ORM的确如此安全。

DbMigrationsConfiguration的源代码:

 ///  /// Runs after upgrading to the latest migration to allow seed data to be updated. /// ///  /// ///  /// Note that the database may already contain seed data when this method runs. This means that /// implementations of this method must check whether or not seed data is present and/or up-to-date /// and then only make changes if necessary and in a non-destructive way. The ///  /// can be used to help with this, but for seeding large amounts of data it may be necessary to do less /// granular checks if performance is an issue. /// If the  database /// initializer is being used, then this method will be called each time that the initializer runs. /// If one of the , , /// or  initializers is being used, then this method will not be /// called and the Seed method defined in the initializer should be used instead. /// ///  /// Context to be used for updating seed data.  

基本上,除了实现“添加或更新”逻辑之外,没有其他选项,因为每次使用初始化程序后都会执行Seed方法。

AddOrUpdate扩展方法对此很有用,但在某些情况下我也使用了它:

  if (!context.Entities.Any()) { // Seed } 

从此页面: 数据库初始化程序和迁移种子方法 :

只要执行Update-Database PowerShell命令,就会运行Configuration类上的Seed方法。 除非正在使用迁移初始化程序,否则在应用程序启动时将不会执行迁移Seed方法。

所以,我认为你这里没有很多选项,如果你运行Update-Database命令,总会调用迁移Seed方法。 我正在挖掘如果存在一个参数给这个命令,让你指定不运行Seed方法,但我很沮丧它还不存在。 这些是您可以使用的所有参数(您可以在此链接中找到更多信息):

 Update-Database [-SourceMigration ] [-TargetMigration ] [-Script] [-Force] [-ProjectName ] [-StartUpProjectName ] [-ConfigurationTypeName ] [-ConnectionStringName ] [-AppDomainBaseDirectory ] [] Update-Database [-SourceMigration ] [-TargetMigration ] [-Script] [-Force] [-ProjectName ] [-StartUpProjectName ] [-ConfigurationTypeName ] -ConnectionString  -ConnectionProviderName  [-AppDomainBaseDirectory ] [] 

如果您正在执行sql脚本以在Seed方法中插入数据,则可以使用booleam条件以避免在第一次之后重新插入相同的字段。

作为附加信息,您的请求中有一个参数可以避免在运行此站点中已存在的Update-Database命令时执行Seed方法,EF团队将使用该命令从社区收集建议。

我将所有种子语句移动到单独的方法中,可以在运行“update-database”之前轻松注释掉。

 protected override void Seed(Tpsc.EDI.EDIContext context) { try { //EDI.Seed.DoSeed(context); } catch (DbEntityValidationException e) { ... } } 

如果您有sql脚本来插入数据并且您希望阻止将来插入,则可以使用sql合并来避免重复。 将您拥有的所有数据插入到具有与目标表相同结构的临时表中,然后使用合并来决定何时插入记录。 如果它们匹配是因为你插入了一次。

假设S是包含所有数据的临时表,T是最终表

 MERGE Target AS T USING Source AS S ON (T.EmployeeID = S.EmployeeID AND T.EmployeeName LIKE 'S%' AND S.EmployeeName LIKE 'S%' ) WHEN NOT MATCHED BY TARGET THEN INSERT(EmployeeID, EmployeeName) VALUES(S.EmployeeID, S.EmployeeName) WHEN MATCHED THEN UPDATE SET T.EmployeeName = S.EmployeeName WHEN NOT MATCHED BY SOURCE THEN DELETE 

有关更多参考资料,请使用https://technet.microsoft.com/en-us/library/bb522522(v=sql.105).aspx

我通常使用命令update-database -sc然后我运行生成的脚本来手动更新数据库。 在开始的时候,我觉得这样做并不舒服,但现在我想看看我的数据库会发生什么事,为时已晚。