マッピング構成ファイルを使用する NHibernate プロジェクトがあります。SQL Server データベースを使用しています。
コードによるマッピングに切り替えたい。私のアプローチは、一度に 1 つのクラスを実行し、切り替えごとにすべてのテストに合格することを確認することです。
2 つのマッピングを混在させるのは非常に簡単です。
public static ISessionFactory SessionFactory
{
get
{
if (_sessionFactory == null)
{
var configuration = new Configuration();
configuration.Configure();
configuration.AddAssembly(typeof(Entities.Player).Assembly);
var mapper = new NHibernate.Mapping.ByCode.ModelMapper();
// Here are the entities I've switched to mapping-by-code
DATMedia.CMS.EntityLibrary.Mappings.ScheduleMediaItem.Map(mapper);
DATMedia.CMS.EntityLibrary.Mappings.Schedule.Map(mapper);
configuration.AddMapping(mapper.CompileMappingForAllExplicitlyAddedEntities());
_sessionFactory = configuration.BuildSessionFactory();
}
return _sessionFactory;
}
}
しかし、Schedule
マッピングをコードごとのマッピングに変更したとき、重大なパフォーマンスの問題が発生しました。の呼び出しにSession.Flush
は 12 秒かかりますが、これはごくわずかな量のテスト データを超えています。
XML マッピングに戻すと、パフォーマンスの問題はなくなりました。
他の誰かが問題を経験しましたか?
schedule
明らかな欠陥がある場合に備えて、の前後のマッピングを含めます。
構成ファイル経由:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="DATMedia.CMS.EntityLibrary.Entities.Schedule, DATMedia.CMS.EntityLibrary" table="cms_Schedule">
<id name="Id" column="Id" type="Int64">
<generator class="identity" />
</id>
<property name="Date" column="Date" type="Timestamp" />
<many-to-one name="SourceTemplate" column="SourceTemplate_Id" class="DATMedia.CMS.EntityLibrary.Entities.ScheduleTemplate, DATMedia.CMS.EntityLibrary" cascade="none" fetch="join" lazy="proxy"/>
<!--
Note that we are not using cascading deletes here.
This will be handled by SQL Server through ON DELETE CASCADE foreign key constraints
-->
<bag name="MediaItems" inverse="true" cascade="save-update" lazy="true" order-by="PlayIndex">
<key column="Schedule_Id" />
<one-to-many class="DATMedia.CMS.EntityLibrary.Entities.ScheduleMediaItem, DATMedia.CMS.EntityLibrary"/>
</bag>
<bag name="PlayerGroups" table="cms_ManyToMany_PlayerGroupSchedules_PlayerGroup_Schedule" lazy="true" cascade="save-update">
<key column="Schedule_Id" />
<many-to-many column="PlayerGroup_Id"
class="DATMedia.CMS.EntityLibrary.Entities.PlayerGroup, NHibernateManyToMany" />
</bag>
</class>
</hibernate-mapping>
コードによるマッピング:
public static void Map(ModelMapper mapper)
{
mapper.Class<DATMedia.CMS.EntityLibrary.Entities.Schedule>(
classMapper =>
{
classMapper.Table("cms_Schedule");
classMapper.Id(x => x.Id, map =>
{
map.Column("Id");
map.Generator(Generators.Identity);
});
classMapper.Property(
s => s.Date,
propertyMapper =>
{
propertyMapper.Column("Date");
propertyMapper.NotNullable(true);
}
);
classMapper.ManyToOne(
s => s.SourceTemplate,
manyToOneMapper =>
{
manyToOneMapper.Column("SourceTemplate_Id");
manyToOneMapper.Cascade(Cascade.None);
manyToOneMapper.Fetch(FetchKind.Join);
manyToOneMapper.Lazy(LazyRelation.Proxy);
}
);
classMapper.Bag(
s => s.MediaItems,
bagPropertyMapper =>
{
bagPropertyMapper.Key(keyMapper =>
{
keyMapper.Column("Schedule_Id");
}
);
bagPropertyMapper.Inverse(true);
bagPropertyMapper.Cascade(Cascade.Persist);
bagPropertyMapper.Lazy(CollectionLazy.Lazy);
bagPropertyMapper.OrderBy(smi => smi.PlayIndex);
}
);
classMapper.Bag(
s => s.PlayerGroups,
bagPropertyMapper =>
{
bagPropertyMapper.Key(keyMapper =>
{
keyMapper.Column("Schedule_Id");
});
bagPropertyMapper.Table("cms_ManyToMany_PlayerGroupSchedules_PlayerGroup_Schedule");
bagPropertyMapper.Lazy(CollectionLazy.Extra);
bagPropertyMapper.Cascade(Cascade.Persist);
},
collectionElementRelation =>
{
collectionElementRelation.ManyToMany(manyToManyMapper =>
{
manyToManyMapper.Column("PlayerGroup_Id");
}
);
}
);
}
);
}
後で編集
Flush
トランザクション内で呼び出さないことで問題を解決しました。
問題を再現するために、より単純なテスト コードを作成しようとしましたが、うまくいきませんでした (Flush を何度呼び出しても、すべてのテスト コードは非常に高速に実行されます)。これは、一部のエンティティのキー生成を から に変換したことが原因である可能性がありIdentity
ますHiLo
。
私の場合、私のコードは問題を引き起こした特定の構成を作成していたようです。
推測すると、問題を引き起こす構成には、実行時間の長いトランザクションの軽率な使用と ID キーの生成の組み合わせが含まれていると言えます。