为什么 Fluent 的 NHibernate 的 AutoMapping 会忽略枚举类型?
Why does AutoMapping from Fluent's NHibernate ignore an enum type?
我有以下枚举类型:
public enum EnumType
{
E1,
E2
}
用于以下class:
public class X
{
public virtual int? Id { get; set; }
public virtual EnumType EnumProperty { get; set; }
public virtual string S { get; set; }
}
我想使用 NHibernate 将这种类型的实例持久保存在数据库中。为了避免编写样板代码,我正在尝试使用自动映射功能,如下所示:
private ISessionFactory CreateSessionFactory()
{
var mappings = AutoMap
.AssemblyOf<Domain.X>(new MyAutoMappingConfiguration());
this.NHibernateConfiguration = Fluently
.Configure()
.Database(FluentNHibernate.Cfg.Db.MsSqlConfiguration.MsSql2012.ConnectionString(
b => b.FromConnectionStringWithKey("x")))
.Mappings(m => m.AutoMappings.Add(mappings))
.BuildConfiguration();
return this.NHibernateConfiguration.BuildSessionFactory();
}
其中 MyAutoMappingConfiguration
看起来像这样:
public class MyAutoMappingConfiguration: FluentNHibernate.Automapping.DefaultAutomappingConfiguration
{
public override bool ShouldMap(Type type)
{
return type.Namespace == "Domain";
}
public override bool IsComponent(Type type)
{
return type.Name == "EnumType";
}
}
当我使用从此配置生成的模式创建数据库时:
new SchemaExport(this.sessionProvider.NHibernateConfiguration)
.Execute(true, true, false);
正在生成并执行以下脚本:
if exists (select * from dbo.sysobjects where id = object_id(N'[X]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) drop table [X]
create table [X] (
Id INT not null,
S NVARCHAR(255) null,
primary key (Id)
)
为什么 属性 EnumProperty
被忽略了?
当我为 X
添加一个显式映射时,或者(看起来等效的)像这样的自动映射覆盖:
var mappings = AutoMap
.AssemblyOf<Domain.X>(new MyAutoMappingConfiguration())
.Override<Domain.X>(m =>
{
m.Table("X");
m.Id(x => x.Id);
m.Map(x => x.EnumProperty); // this works
m.Map(x => x.S);
});
脚本生成正确:
if exists (select * from dbo.sysobjects where id = object_id(N'[X]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) drop table [X]
create table [X] (
Id INT not null,
EnumProperty NVARCHAR(255) null,
S NVARCHAR(255) null,
primary key (Id)
)
这表明 NHibernate 正确映射呈现的枚举的能力似乎没有任何问题。为什么自动映射不能解决这个问题?
当我将以下方法添加到MyAutoMappingConfiguration
时:
public override bool ShouldMap(Member member)
{
var result = base.ShouldMap(member);
return result;
}
并放置断点,对于 EnumProperty
成员,result
是 true
,稍后会以某种方式被忽略。
根据我的经验,枚举是开箱即用的映射,根本不需要做任何额外的事情(没有自定义类型或组件)。
所以,有两个问题:
IsComponent
不应表示所讨论的枚举是一个组件:
public override bool IsComponent(Type type)
{
return base.IsComponent(type);
}
(或者完全删除实现)
ShouldMap
不应表示枚举需要显式映射。它无论如何都会被映射,因为它是 属性。所以,例如:
public override bool ShouldMap(Member member)
{
return base.ShouldMap(member) && member.CanWrite &&
!member.MemberInfo.IsDefined(typeof(NotMappedAttribute), false);
}
在你的例子中,如果枚举在同一个命名空间中,你应该这样做:
public override bool ShouldMap(Type type)
{
return type.Namespace == "Domain"
&& !type.IsEnum;
}
(有点counter-intuitive)
我有以下枚举类型:
public enum EnumType
{
E1,
E2
}
用于以下class:
public class X
{
public virtual int? Id { get; set; }
public virtual EnumType EnumProperty { get; set; }
public virtual string S { get; set; }
}
我想使用 NHibernate 将这种类型的实例持久保存在数据库中。为了避免编写样板代码,我正在尝试使用自动映射功能,如下所示:
private ISessionFactory CreateSessionFactory()
{
var mappings = AutoMap
.AssemblyOf<Domain.X>(new MyAutoMappingConfiguration());
this.NHibernateConfiguration = Fluently
.Configure()
.Database(FluentNHibernate.Cfg.Db.MsSqlConfiguration.MsSql2012.ConnectionString(
b => b.FromConnectionStringWithKey("x")))
.Mappings(m => m.AutoMappings.Add(mappings))
.BuildConfiguration();
return this.NHibernateConfiguration.BuildSessionFactory();
}
其中 MyAutoMappingConfiguration
看起来像这样:
public class MyAutoMappingConfiguration: FluentNHibernate.Automapping.DefaultAutomappingConfiguration
{
public override bool ShouldMap(Type type)
{
return type.Namespace == "Domain";
}
public override bool IsComponent(Type type)
{
return type.Name == "EnumType";
}
}
当我使用从此配置生成的模式创建数据库时:
new SchemaExport(this.sessionProvider.NHibernateConfiguration)
.Execute(true, true, false);
正在生成并执行以下脚本:
if exists (select * from dbo.sysobjects where id = object_id(N'[X]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) drop table [X]
create table [X] (
Id INT not null,
S NVARCHAR(255) null,
primary key (Id)
)
为什么 属性 EnumProperty
被忽略了?
当我为 X
添加一个显式映射时,或者(看起来等效的)像这样的自动映射覆盖:
var mappings = AutoMap
.AssemblyOf<Domain.X>(new MyAutoMappingConfiguration())
.Override<Domain.X>(m =>
{
m.Table("X");
m.Id(x => x.Id);
m.Map(x => x.EnumProperty); // this works
m.Map(x => x.S);
});
脚本生成正确:
if exists (select * from dbo.sysobjects where id = object_id(N'[X]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) drop table [X]
create table [X] (
Id INT not null,
EnumProperty NVARCHAR(255) null,
S NVARCHAR(255) null,
primary key (Id)
)
这表明 NHibernate 正确映射呈现的枚举的能力似乎没有任何问题。为什么自动映射不能解决这个问题?
当我将以下方法添加到MyAutoMappingConfiguration
时:
public override bool ShouldMap(Member member)
{
var result = base.ShouldMap(member);
return result;
}
并放置断点,对于 EnumProperty
成员,result
是 true
,稍后会以某种方式被忽略。
根据我的经验,枚举是开箱即用的映射,根本不需要做任何额外的事情(没有自定义类型或组件)。
所以,有两个问题:
IsComponent
不应表示所讨论的枚举是一个组件:public override bool IsComponent(Type type) { return base.IsComponent(type); }
(或者完全删除实现)
ShouldMap
不应表示枚举需要显式映射。它无论如何都会被映射,因为它是 属性。所以,例如:public override bool ShouldMap(Member member) { return base.ShouldMap(member) && member.CanWrite && !member.MemberInfo.IsDefined(typeof(NotMappedAttribute), false); }
在你的例子中,如果枚举在同一个命名空间中,你应该这样做:
public override bool ShouldMap(Type type) { return type.Namespace == "Domain" && !type.IsEnum; }
(有点counter-intuitive)