2

我有一个带有一些自定义功能的 Umbraco CMS 应用程序,我使用 PetaPOCO 将数据存储在我的数据库中。我创建了我的 POCO 和一个 Umbraco 事件,该事件在应用程序启动时触发以创建表(如果它不存在):

public class RegisterEvents : ApplicationEventHandler
{
    //This happens everytime the Umbraco Application starts
    protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
    {
        //Get the Umbraco Database context
        var db = applicationContext.DatabaseContext.Database;

        //Check if the DB table does NOT exist
        if (!db.TableExist("MyTable"))
        {
            //Create DB table - and set overwrite to false
            db.CreateTable<MyPetaPOCO>(false);
        }
    }
}

如何在不直接访问数据库的情况下修改现有数据库(我想添加一列)?我需要使用代码,因为主机还没有提供访问权限。我想我应该能够在这个 ApplicationStarted 覆盖事件中做到这一点,但我不知道如何。

编辑

我应该使用什么东西Fluent Migrator

4

2 回答 2

7

如果这是一个包或您正在部署(或让其他人使用)的东西,您应该创建一个迁移并在您的 ApplicationStarted 方法中运行它。

https://cultiv.nl/blog/using-umbraco-migrations-to-deploy-changes/

上述文章中的示例:

要将列添加到现有 PetaPOCO DB:

创建一个从 MigrationBase 派生的迁移类:

[Migration("1.0.1", 1, "YourTableName")]
  public class AddNewColumnToTable : MigrationBase
  {
    public AddNewColumnToTable(ISqlSyntaxProvider sqlSyntax, ILogger logger) 
      : base(sqlSyntax, logger)
    { }

    public override void Up()
    {
      Alter.Table("YourTableName").AddColumn("ColumnToAdd").AsString().Nullable();
    }

    public override void Down()
    {
      Delete.Column("ColumnToAdd").FromTable("YourTableName");
    }
  }

更新您ApplicationStarted的逻辑以运行迁移:

  public class MyApplication : ApplicationEventHandler
  {
    protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
    {
      HandleStatisticsMigration();
    }

    private static void HandleStatisticsMigration()
    {
      const string productName = "YourTableName";
      var currentVersion = new SemVersion(0, 0, 0);

      // get all migrations for "YourTableName" already executed
      var migrations = ApplicationContext.Current.Services.MigrationEntryService.GetAll(productName);

     // get the latest migration for "YourTableName" executed
     var latestMigration = migrations.OrderByDescending(x => x.Version).FirstOrDefault();

     if (latestMigration != null)
       currentVersion = latestMigration.Version;

     var targetVersion = new SemVersion(1, 0, 1);
     if (targetVersion == currentVersion)
       return;

     var migrationsRunner = new MigrationRunner(
       ApplicationContext.Current.Services.MigrationEntryService,
       ApplicationContext.Current.ProfilingLogger.Logger,
       currentVersion,
       targetVersion,
       productName);

     try
     {
       migrationsRunner.Execute(UmbracoContext.Current.Application.DatabaseContext.Database);
     }
     catch (Exception e)
     {
       LogHelper.Error<MyApplication>("Error running YourTableName migration", e);
     }
   }
 }

请注意,目标版本应与您在Migration类属性中设置的版本相匹配(在本例中为 1.0.1)

当您进行更新并向应用程序或插件添加新功能时,您会创建新的迁移(如果需要)并更新目标版本。

于 2016-09-13T17:23:12.817 回答
2

如果你使用 PetaPoco,你可以使用,db.Execute("alter table ...")但是你需要有足够的访问权限来执行这样的 DDL 语句。

此外,我也会在 PetaPoco 事务中运行它,因为这是一种很好的做法。

最后,如果您在 Application_Start 上运行它(这很好),您需要执行检查以确保该列不存在。

于 2013-08-28T10:06:41.707 回答