gpt4 book ai didi

c# - Fluent NHibernate table per hierarchy 映射问题

转载 作者:行者123 更新时间:2023-11-30 17:24:12 26 4
gpt4 key购买 nike

我使用的是 Fluent NHibernate 版本 1.0.0.579(当前最新版本)。我有一个抽象的 Activity 类和几个继承类,例如。虚拟事件。它们都使用同一个表事件,并且它们都有一个基于整数类型的鉴别器值,该值指向项目中的映射(而不是数据库中的 FK)。

我们这样构建映射:

public class ActivityMap : ClassMap<Activity>
{
public ActivityMap()
{
Table("Activities");
Id(x => x.Id).Column("ID").GeneratedBy.Guid();
Map(x => x.ActivityName).Not.Nullable().Length(50);
HasMany(x => x.ActivityParameters)
.KeyColumn("ActivityID")
.AsMap<string>(idx => idx.Column("ParameterName"), elem => elem.Column("ParameterValue"))
.Not.LazyLoad()
.Cascade.Delete()
.Table("ActivityParameters");

DiscriminateSubClassesOnColumn<int>("ActivityType")
.SubClass<DummyActivity>(1, c => { });
}
}

生成的hbm.xml文件为:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="property" auto-import="true" default-cascade="none" default-lazy="true">
<class xmlns="urn:nhibernate-mapping-2.2" name="***.Activity, ***, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="Activities">
<id name="Id" type="System.Guid, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="ID" />
<generator class="guid" />
</id>
<discriminator column="ActivityType" type="Int32" insert="true" not-null="true" />
<property name="ActivityName" type="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="ActivityName" length="50" not-null="true" />
</property>
<map cascade="delete" lazy="false" name="ActivityParameters" table="ActivityParameters">
<key>
<column name="ActivityID" />
</key>
<index type="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="ParameterName" />
</index>
<element type="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="ParameterValue" />
</element>
</map>
<subclass name="***.DummyActivity, ***, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" discriminator-value="1" />
</class>
</hibernate-mapping>

据我所知,这看起来像一个有效的 hbm.xml 文件,在结构上与官方 NHibernate 引用文档中给出的示例相同,即

<class name="IPayment" table="PAYMENT">
<id name="Id" type="Int64" column="PAYMENT_ID">
<generator class="native"/>
</id>
<discriminator column="PAYMENT_TYPE" type="String"/>
<property name="Amount" column="AMOUNT"/>
...
<subclass name="CreditCardPayment" discriminator-value="CREDIT">
...
</subclass>
<subclass name="CashPayment" discriminator-value="CASH">
...
</subclass>
<subclass name="ChequePayment" discriminator-value="CHEQUE">
...
</subclass>
</class>

我们是不是在映射中犯了一些错误?另外,有人可以指出 Fluent 推荐的新实现吗(使用带有鉴别器列的子类,比如

public class ActivityMap : ClassMap<Activity>
{
public ActivityMap()
{
Table("Activities");
Id(x => x.Id).Column("ID").GeneratedBy.Guid();
Map(x => x.ActivityName).Not.Nullable().Length(50);
HasMany(x => x.ActivityParameters)
.KeyColumn("ActivityID")
.AsMap<string>(idx => idx.Column("ParameterName"), elem => elem.Column("ParameterValue"))
.Not.LazyLoad()
.Cascade.Delete()
.Table("ActivityParameters");

DiscriminateSubClassesOnColumn<int>("ActivityType");
}
}

public class DummyActivityMap : SubClass<DummyActivity>
{
///discriminator value here how???
}

?)

堆栈跟踪是

[FormatException: Input string was not in a correct format.]
System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal) +7469351
System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info) +119
NHibernate.Type.Int32Type.FromStringValue(String xml) +36
NHibernate.Type.Int32Type.StringToObject(String xml) +10
NHibernate.Persister.Entity.SingleTableEntityPersister..ctor(PersistentClass persistentClass, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory, IMapping mapping) +7824

[MappingException: Could not format discriminator value to SQL string of entity ***.Activity]
NHibernate.Persister.Entity.SingleTableEntityPersister..ctor(PersistentClass persistentClass, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory, IMapping mapping) +8183
NHibernate.Persister.PersisterFactory.CreateClassPersister(PersistentClass model, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory, IMapping cfg) +68
NHibernate.Impl.SessionFactoryImpl..ctor(Configuration cfg, IMapping mapping, Settings settings, EventListeners listeners) +1468
NHibernate.Cfg.Configuration.BuildSessionFactory() +87
FluentNHibernate.Cfg.FluentConfiguration.BuildSessionFactory() in d:\Builds\FluentNH\src\FluentNHibernate\Cfg\FluentConfiguration.cs:93

[FluentConfigurationException: An invalid or incomplete configuration was used while creating a SessionFactory. Check PotentialReasons collection, and InnerException for more detail.

]
***.Container.ConfigureNHibernate() in ***.Unity\Container.cs:92
***.Container.ConfigureContainer() in ***.Unity\Container.cs:60
***.Container.GetInstance() in ***.Unity\Container.cs:45
***.Global.CreateContainer() in ***\Global.asax.cs:72
***.Global.Application_Start(Object sender, EventArgs e) in ***\Global.asax.cs:44

最佳答案

我在枚举的情况下想通了。

考虑到这个枚举类型:

public enum ActivityType
{
[EnumKey("1")]
[EnumDescription("ImportFromFile")]
ImportFromFile,
}

其中 EnumKey 和 EnumDescription 是(流行的)扩展方法,我像这样重新定义 Activity

public abstract class Activity
{
public virtual Guid Id { get; set; }
public virtual ActivityExecutionResult ExecutionResult { get; private set; }

public virtual ActivityExecutionStatus ExecutionStatus {get;private set;}

public abstract ActivityExecutionStatus Execute();

public virtual string ActivityName { get; private set; }

public virtual IDictionary<string, string> ActivityParameters { get; private set; }

public virtual ActivityType ActivityType { get; private set; }
}

映射文件如下所示:

public class ActivityMap : ClassMap<Activity>
{
public ActivityMap()
{
Table("Activities");
Id(x => x.Id).Column("ID").GeneratedBy.Guid();
Map(x => x.ActivityName).Not.Nullable().Length(50);
Map(x => x.ActivityType).CustomType<int>().Column("ActivityType").Not.Nullable();
HasMany(x => x.ActivityParameters)
.KeyColumn("ActivityID")
.AsMap<string>(idx => idx.Column("ParameterName"), elem => elem.Column("ParameterValue"))
.Not.LazyLoad()
.Cascade.Delete()
.Table("ActivityParameters");

DiscriminateSubClassesOnColumn("ActivityType");
}
}

public class ImportActivityFromFileMap : SubclassMap<ImportActivityFromFile>
{
public ImportActivityFromFileMap()
{
DiscriminatorValue(ActivityType.ImportFromFile.GetKey());
}
}

生成的 hbm 文件如下所示:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="property" auto-import="true" default-cascade="none" default-lazy="true">
<class xmlns="urn:nhibernate-mapping-2.2" name="***.Activity, ***, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="Activities">
<id name="Id" type="System.Guid, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="ID" />
<generator class="guid" />
</id>
<discriminator column="ActivityType" type="String" insert="true" not-null="true" />
<property name="ActivityName" type="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="ActivityName" length="50" not-null="true" />
</property>
<property name="ActivityType" type="Int32">
<column name="ActivityType" not-null="true" />
</property>
<map cascade="delete" lazy="false" name="ActivityParameters" table="ActivityParameters">
<key>
<column name="ActivityID" />
</key>
<index type="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="ParameterName" />
</index>
<element type="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="ParameterValue" />
</element>
</map>
<subclass name="***.ImportActivityFromFile, ***, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" discriminator-value="1" />
</class>
</hibernate-mapping>

它就像一个魅力!

关于c# - Fluent NHibernate table per hierarchy 映射问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1345426/

26 4 0