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...
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With