EF6 - Run Update-Database Command without seeds

一世执手 提交于 2019-12-06 21:02:36

问题


I'm Using Entity Framework 6 and I'm using migrations. I have already created the database using an initial migration. Now I have done changes to the Model and the context has changed, and I want to update the database BUT... When I try to run again the Database-Update command the seeds are also running too, and this bring errores due some data is inserted again.

So, how can I to run the Update-Database command WITHOUT running the seed method?


It is hard to believe that EF doesn't have any simple option like -No-Seed for that. I'm almost secure that other ORMs does.


回答1:


From the source code of DbMigrationsConfiguration<TContext>:

/// <summary>
    /// Runs after upgrading to the latest migration to allow seed data to be updated.
    /// 
    /// </summary>
    /// 
    /// <remarks>
    /// 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
    ///             <see cref="M:System.Data.Entity.Migrations.DbSetMigrationsExtensions.AddOrUpdate``1(System.Data.Entity.IDbSet{``0},``0[])"/>
    ///             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 <see cref="T:System.Data.Entity.MigrateDatabaseToLatestVersion`2"/> database
    ///             initializer is being used, then this method will be called each time that the initializer runs.
    ///             If one of the <see cref="T:System.Data.Entity.DropCreateDatabaseAlways`1"/>, <see cref="T:System.Data.Entity.DropCreateDatabaseIfModelChanges`1"/>,
    ///             or <see cref="T:System.Data.Entity.CreateDatabaseIfNotExists`1"/> initializers is being used, then this method will not be
    ///             called and the Seed method defined in the initializer should be used instead.
    /// 
    /// </remarks>
    /// <param name="context">Context to be used for updating seed data. </param>

Basically, you don't have another option than implement an "add or update" logic because the Seed method will be executed each time after the initializer is used.

The AddOrUpdate extension method is useful for this, but I have also used this in some cases:

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



回答2:


From this page:Database initializer and Migrations Seed methods:

The Seed method on the Configuration class runs whenever the Update-Database PowerShell command is executed. Unless the Migrations initializer is being used the Migrations Seed method will not be executed when your application starts.

So, I think you don't have many options here, the migration Seed method always will be called if you run Update-Database command. I was digging if exist a parameter to this command that let you specify not run the Seed method, but I'm fraid it don't exist yet. These are all the parameters you can use (you can find more info in this link):

Update-Database [-SourceMigration <String>] [-TargetMigration <String>] [-Script] [-Force] 
  [-ProjectName <String>] [-StartUpProjectName <String>] [-ConfigurationTypeName <String>] 
  [-ConnectionStringName <String>] [-AppDomainBaseDirectory <String>] [<CommonParameters>]

Update-Database [-SourceMigration <String>] [-TargetMigration <String>] [-Script] [-Force] 
  [-ProjectName <String>] [-StartUpProjectName <String>] [-ConfigurationTypeName <String>] 
  -ConnectionString <String> -ConnectionProviderName <String> 
  [-AppDomainBaseDirectory <String>] [<CommonParameters>]

If you are executing a sql script to insert data in the Seed method, you could use a booleam condition to avoid reinsert the same fields after the first time.

As an aditional info, your request in have a parameter to avoid execute the Seed method when you run the Update-Database command already exist in this site, which is used by EF team to collect suggestions from the community.




回答3:


I moved all my seed statements into separate methods that can be commented out easily before running 'update-database'.

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



回答4:


I usually use the command update-database -sc then I run the script generated to update database manually. I didn't feel confortable to do this in the beggining, but now I like to see what is going to happen with my database before its too late.




回答5:


If you have sql scripts to insert the data and you want to prevent future insertions, the you can user a sql merge to avoid duplicates. Insert all the data that you have in a temp table with the same structure of your target table and then use the merge to decide when you will insert the records or not. If they match is because you inserted once.

Supposed S is your temp table with all your data and T the final table

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

for more references use https://technet.microsoft.com/en-us/library/bb522522(v=sql.105).aspx




回答6:


Old question, but always useful. So my contribute is: use ConfigurationManager options in your web.config/app.config.

This is possible as System.Configuration.ConfigurationManager is accessible from your Configuration class.

Do it in this way:

public sealed class Configuration : DbMigrationsConfiguration<Booking.EntityFramework.BookingDbContext> {

    public Configuration() {
       // ...
    }

    protected override void Seed(Booking.EntityFramework.BookingDbContext context) {
        // check configuration if seed must be skipped
        if (!bool.Parse(ConfigurationManager.AppSettings["Database.Seed"] ?? bool.TrueString)) return;

        // if here, seed your database
        // ...
    }
}

In this way you can define an application setting in the web.config or app.config file:

<appSettings>
  <add key="Database.Seed" value="false" />  <!-- <== do not seed! -->
  ...
</appSettings>


来源:https://stackoverflow.com/questions/28635377/ef6-run-update-database-command-without-seeds

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!