We have been looking at using Envers, but have run into a road block. We use a table/class structure that is using table per class inheritance for a couple of classes. While NHibernate and Envers are loading, an error occurs when it tries to create the tables for the subclasses.
NHibernate.MappingException: Unable to build the insert statement for class Demo.Vehicle_AUD: a failure occured when adding the discriminator ---> System.ArgumentException: The column 'VehicleTypeId' has already been added in this SQL builder
Parameter name: columnName
Here is an example similar to what we are using.
// Maps to Vehicle table
public Vehicle
{
public int VehicleId {get;set;}
pubic VehicleType VehicleTypeId {get;set;}
}
// Maps to Vehicle table with discriminator for VehicleTypeId == Car
public Car : Vehicle
{
public decimal MaxSpeed {get;set;}
}
// Maps to Vehicle table with discriminator for VehicleType == Airplane
public Airplane : Vehicle
{
public decimal MaxAirspeed {get;set;}
public decimal MaxAltitude {get;set;}
}
Table definition:
VehicleId int identity primary key
VehicleTypeId int foreign key to VehicleTypeId on VehicleType table
MaxSpeed decimal null
MaxAirspeed decimal null
MaxAltitude decimal null
We are using FluentNHibernate:
var fluentConfig = FetchDbConfiguration(connectionString)
.Mappings(mapper =>
{
mapper.FluentMappings.AddFromAssemblyOf<Vehicle>()
})
.ExposeConfiguration(cfg =>
{
var enversConf = new FluentConfiguration();
//enversConf.Audit<Vehicle>();
enversConf.Audit<Car>();
enversConf.Audit<Airplane>();
nhConf.IntegrateWithEnvers(enversConf);
});
var nhConfiguration = fluentConfig.BuildConfiguration();
return nhConfiguration;
Mappings:
public partial class VehicleMap : ClassMap<Vehicle>
{
public VehicleMap()
{
Table("Vehicle");
LazyLoad();
Id(x => x.VehicleId)
.Column("VehicleId")
.CustomType("Int32")
.Access.Property()
.Not.Nullable()
.Precision(10)
.GeneratedBy.Identity();
DiscriminateSubClassesOnColumn("VehicleTypeId", 0)
.CustomType<int>()
.ReadOnly()
.SqlType("int")
.Not.Nullable();
}
}
public partial class CarMap : SubclassMap<Car>
{
public CarMap()
{
DiscriminatorValue(1); // 1 = Car
Map(x => x.MaxSpeed)
.Column("MaxSpeed")
.CustomType("Decimal")
.Access.Property()
.Generated.Never()
.Default(@"0")
.Precision(19)
.Scale(4);
}
}
Airplane is mapped similarly to car using SubclassMap
The error seems to be happening because Envers is trying to create the Vehicle table for both of the subclasses. I have tried different variations of including/excluding the Vehicle class for auditing.
My first question is does Envers support the use table per class inheritance? If it does, can anyone point me to examples/documentation on how to configure it for table per class?
Thanks.