运行 设置 NHibernate Envers 的问题 table 每个 class 映射
Running into problem setting NHibernate Envers with table per class mapping
我们一直在考虑使用 Envers,但 运行 遇到了障碍。我们使用 table/class 结构,每个 class 继承使用 table 几个 classes。在加载 NHibernate 和 Envers 时,当它尝试为子 classes 创建 tables 时会发生错误。
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
这是一个类似于我们正在使用的示例。
// 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定义:
VehicleId int identity primary key
VehicleTypeId int foreign key to VehicleTypeId on VehicleType table
MaxSpeed decimal null
MaxAirspeed decimal null
MaxAltitude decimal null
我们正在使用 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;
映射:
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);
}
}
飞机的映射类似于汽车使用 SubclassMap
错误的发生似乎是因为 Envers 正在尝试为两个子 class 创建载具 table。我尝试了 including/excluding 车辆 class 的不同变体进行审核。
我的第一个问题是 Envers 是否支持每个 class 继承使用 table?如果是这样,谁能告诉我 examples/documentation 如何根据 class 为 table 配置它?
谢谢。
我们根据 class 方法同时使用 Envers 和 table,我们通常映射基础 class 然后我们使用 Join table 来定义派生 class
试试这样:
public class VehicleMap : ClassMap<Vehicle>
{
public VehicleMap() {
Table("Vehicle");
Id(_ => _.Id, "VehicleId")...
DiscriminateSubClassesOnColumn("VehicleTypeId");
...
}
和汽车
public class CarMap : SubclassMap<Car>
{
public CarMap() {
Table("cars");
DiscriminatorValue(1);
Join("cars", part => {
part.KeyColumn("VehicleId");
part.Map(x => x.MaxSpeed) ...
这相当于 9.1.2 中描述的映射 https://nhibernate.info/doc/nhibernate-reference/inheritance.html
对于 Envers,只需添加包括基数 1 在内的所有类型。
事实证明,我们正在使用 Envers 尚不支持的鉴别器属性来映射我们的 classes。我们的鉴别器列映射到另一个 object/table,而不是基本类型。我们提交了一个小补丁来添加对它的支持。
https://github.com/nhibernate/nhibernate-envers/commit/9ae9555ec5e4d4443d5d5ff18c97bf1685278b8e
我们将鉴别器的插入属性设置为 false,以便 NHibernate 知道该列映射到另一个 class。
https://nhibernate.info/doc/nh/en/index.html#mapping-declaration-discriminator
insert (optional - defaults to true): set this to false if your
discriminator column is also part of a mapped composite identifier.
Envers 生成的审核 table 映射不包括此设置,因此当 NHibernate 加载生成的 class 映射时,它尝试为基础 class 和子 classes。这就是导致我们遇到的问题的原因。我们提交的补丁寻找这种类型的映射,然后将 insert="false"
属性添加到鉴别器元素。
我们一直在考虑使用 Envers,但 运行 遇到了障碍。我们使用 table/class 结构,每个 class 继承使用 table 几个 classes。在加载 NHibernate 和 Envers 时,当它尝试为子 classes 创建 tables 时会发生错误。
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
这是一个类似于我们正在使用的示例。
// 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定义:
VehicleId int identity primary key
VehicleTypeId int foreign key to VehicleTypeId on VehicleType table
MaxSpeed decimal null
MaxAirspeed decimal null
MaxAltitude decimal null
我们正在使用 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;
映射:
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);
}
}
飞机的映射类似于汽车使用 SubclassMap
错误的发生似乎是因为 Envers 正在尝试为两个子 class 创建载具 table。我尝试了 including/excluding 车辆 class 的不同变体进行审核。
我的第一个问题是 Envers 是否支持每个 class 继承使用 table?如果是这样,谁能告诉我 examples/documentation 如何根据 class 为 table 配置它?
谢谢。
我们根据 class 方法同时使用 Envers 和 table,我们通常映射基础 class 然后我们使用 Join table 来定义派生 class 试试这样:
public class VehicleMap : ClassMap<Vehicle>
{
public VehicleMap() {
Table("Vehicle");
Id(_ => _.Id, "VehicleId")...
DiscriminateSubClassesOnColumn("VehicleTypeId");
...
}
和汽车
public class CarMap : SubclassMap<Car>
{
public CarMap() {
Table("cars");
DiscriminatorValue(1);
Join("cars", part => {
part.KeyColumn("VehicleId");
part.Map(x => x.MaxSpeed) ...
这相当于 9.1.2 中描述的映射 https://nhibernate.info/doc/nhibernate-reference/inheritance.html
对于 Envers,只需添加包括基数 1 在内的所有类型。
事实证明,我们正在使用 Envers 尚不支持的鉴别器属性来映射我们的 classes。我们的鉴别器列映射到另一个 object/table,而不是基本类型。我们提交了一个小补丁来添加对它的支持。
https://github.com/nhibernate/nhibernate-envers/commit/9ae9555ec5e4d4443d5d5ff18c97bf1685278b8e
我们将鉴别器的插入属性设置为 false,以便 NHibernate 知道该列映射到另一个 class。
https://nhibernate.info/doc/nh/en/index.html#mapping-declaration-discriminator
insert (optional - defaults to true): set this to false if your discriminator column is also part of a mapped composite identifier.
Envers 生成的审核 table 映射不包括此设置,因此当 NHibernate 加载生成的 class 映射时,它尝试为基础 class 和子 classes。这就是导致我们遇到的问题的原因。我们提交的补丁寻找这种类型的映射,然后将 insert="false"
属性添加到鉴别器元素。