Orchard CMS - new properties not updating after migration
Asked Answered
Y

4

8

I am writing a custom module that retrieves and pushes data directly from the Orchard DB using an injected IRepository.

This works fine until i need to update a content part. I add an update in my migrations class and the update runs through (DB schema updated with default values), however I can't update any of the new values through IRepository. I have to drop down into the NHibernate.ISession to flush the changes through.

This all works fine on a newly created recipe, it's only when i alter a part. Here are the key code snippets:

public class TranslationsPartRecord : ContentPartRecord
{
    internal const string DefaultProductName = "Product";

    public TranslationsPartRecord()
    {
        ProductName = DefaultProductName;
    }

    public virtual string ProductName { get; set; }
}

public class TranslationsPart : ContentPart<TranslationsPartRecord>
{
    public string ProductName
    {
        get { return Record.ProductName; }
        set { Record.ProductName = value; }
    }
}

public class TranslationsHandler : ContentHandler
{
    public TranslationsHandler(IRepository<TranslationsPartRecord> repository)
    {
        Filters.Add(StorageFilter.For(repository));
    }
}

public class Migrations : DataMigrationImpl
{
    public int Create()
    {
        SchemaBuilder.CreateTable("TranslationsPartRecord", table => table
            .Column<int>("Id", column => column.PrimaryKey().Identity())
            .Column("ProductName", DbType.String, column => column.NotNull().WithDefault(TranslationsPartRecord.DefaultProductName))
        );

        return 1;
    }

    public int UpdateFrom1()
    {
        SchemaBuilder.AlterTable("TranslationsPartRecord", table => table.AddColumn("ProductDescription", DbType.String, column => column.NotNull().WithDefault(TranslationsPartRecord.DefaultProductDescription)));

        return 2;
    }
}

When i add the second property "ProductDescription" in this example, after the update is run the columns appear in the DB but i cannot update them until i recreate the Orchard recipe (blat App_Data and start again).

here's how I am trying to update:

// ctor
    public AdminController(IRepository<TranslationsPartRecord> translationsRepository)
    {
        _translationsRepository = translationsRepository;
    }

[HttpPost]
    public ActionResult Translations(TranslationsViewModel translationsViewModel)
    {
        var translations = _translationsRepository.Table.SingleOrDefault();
        translations.ProductName = translationsViewModel.ProductName;
        translations.ProductDescription = translationsViewModel.ProductDescription;

        _translationsRepository.Update(translations);
        _translationsRepository.Flush();
    }

and here's the NHibernate "fix":

var session = _sessionLocator.For(typeof(TranslationsPartRecord));

        var translations = _translationsRepository.Table.SingleOrDefault();

        // is translations.Id always 1?
        var dbTranslations = session.Get<TranslationsPartRecord>(translations.Id);

        dbTranslations.ProductName = translationsViewModel.ProductName;
        dbTranslations.ProductDescription = translationsViewModel.ProductDescription;

        session.Update(dbTranslations);
        session.Flush();

which seems a bit kludgey...

Cheers.

ps i'm still running Orchard 1.3.9

pps after more testing, the NHibernate fix has stopped working now, so perhaps my initial findings were a red herring. It seems as though new properties on the content part are totally ignored by NHibernate when updating/retrieving - as though the object definition is cached somewhere...

Yount answered 15/3, 2012 at 9:29 Comment(0)
S
8

If your mappings aren't being updated that is strange. You can try to force it by deleting the mappings.bin in the app_data folder, and restarting the application. Orchard should recreate the nhibernate mappings and save as mappings.bin.

Satanism answered 15/3, 2012 at 20:34 Comment(3)
thanks for that info, didn't realise the mappings were being persisted here. deleting this file, then disabling/enabling the module did the trick, although not convinced this is the answer i am looking for :) I'm just wondering if i'm circumventing Orchard process by doing it like this?Yount
I found that I am running into this same issue, and your solution worked, but just like @MikeSimmons, I find this method a strange way to accomplish this. Is this truly the best method? FYI - I am using Orchard 1.6.Brainchild
I am running Orchard 1.10 and just added a property to my ContentPart and found I also had to delete the mappings file. This is a worry, because I would like to release my module and this would make upgrades difficult.Bronchi
P
2

I have ran into the same issue, and the only way around it that I can find is to delete mappings.bin (I don't need to disable and re-enable the module). In fact, this is the answer that I got from Bertrand when I asked why this was happening.

I have logged this as an issue at http://orchard.codeplex.com/workitem/19306. If you could vote this up, then we may get it looked at quicker.

Prolongate answered 7/12, 2012 at 16:26 Comment(0)
F
0

This seems like a similar issue to what I am seeing... I am seeing that when you enable a module, it runs the NHibernate mappings BEFORE running the Migrations..

https://orchard.codeplex.com/workitem/19603

Josh

Fortress answered 12/4, 2013 at 16:5 Comment(0)
C
0

Update the hash value in the ComputingHash method in the PersistenceConfiguration Class, updating the hash value may recreate the mappings.bin file.

    public class PersistenceConfiguration : ISessionConfigurationEvents
    {
      public void Created(FluentConfiguration cfg, AutoPersistenceModel defaultModel)
      {
          DoModelMapping(cfg, defaultModel);
      }

      public void ComputingHash(Hash hash)
      {
          hash.AddString("Some_strings_to_update_hash");
      }

      private void DoModelMapping(FluentConfiguration cfg, AutoPersistenceModel defaultModel)
      {

             // mappings here....
      }

      public void Prepared(FluentConfiguration cfg) { }

      public void Building(Configuration cfg) { }

      public void Finished(Configuration cfg) { }
    }
Communard answered 9/8, 2018 at 16:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.