SchemaUpdate generates duplicate foreign keys

We have a typical web application that its data access layer is written using Castle ActiveRecord. Castle ActiveRecord exposes NHibernate’s SchemUpdate feature. This feature lets us to upgrade schema/database with current changes in domain entities.

One odd problem with SchemaUpdate was that in many cases it was generating foreign keys again without any change in domain entity. After some search I found that if you did not specify foreign key names explicitly, NHibernate generates them randomly. So in update progress becuase name of existing foreign keys are not equal to new generated ones, they are generated again as duplicate.

Solution is very easy. Wherever you use BelognsTo you must specify a fixed name for ForeignKey attribute. This way a none random name is generated for foreign key names. Be aware that foreign key names must be unique across a database.

An example:

[BelongsTo(Column="Owner_ID", ForeignKey="FK_Owner_ID")]
public virtual SomeType Owner { set; get; }

Update Schema in Castle ActiveRecord

NHibernate has a feature named “Schema Update”. This feature help updating schema of existing database based on new changes in mapping files. Schema update do not change current data, just changes schema (table, view, … structure) in an additive manner. Castle ActiveRecord exposes this feature too.

The problem is with NHibernate you have choice for seeing update scripts first and if you were satisfied then do actual update. But in Castle ActiveRecord you must do actual update without any preview of possible changes. This is all because ActiveRecordStarter.UpdateSchema() does not emit NHibernate.SchemaUpdate.Execute’s parameters “scriptAction” and “doUpdate” to the user. It calls SchemaUpdate as follow:

updater.Execute(false, true);

As I needed schema update in Castle ActiveRecord with preview update scripts option, I wrote a method for it:

private static IList UpdateSchema(Action action, bool doUpdate)
{
CheckInitialized();
ArrayList exceptions = new ArrayList();


foreach (Configuration config in ActiveRecordMediator.GetSessionFactoryHolder().GetAllConfigurations())
{
SchemaUpdate updater = CreateSchemaUpdate(config);

try
{
updater.Execute(action, doUpdate);

exceptions.AddRange((IList)updater.Exceptions);
}
catch (Exception ex)
{
throw new ActiveRecordException("Could not update the schema", ex);
}
}

return exceptions;
}

private static void CheckInitialized()
{
if (!ActiveRecordStarter.IsInitialized)
{
throw new ActiveRecordException("Framework must be Initialized first.");
}
}

private static SchemaUpdate CreateSchemaUpdate(Configuration cfg)
{
return new SchemaUpdate(cfg);
}

Hope Castle ActiveRecord add an overload to ActiveRecordStarter.UpdateSchema that let seeing update schema scripts before actually doing the update.