メソッドごとに 1 つのセッションで nHibernate を使用しています。メソッドを実行する前にCastle Dynamic Proxyを使用してセッションとトランザクションを開き、このメソッドの実行直後にトランザクションをコミットしてセッションを閉じます。
SQLite データベースを使用していますが、cascade を SaveUpdate または None に設定しても何も変わりません。nHIbernate は、デフォルト構成の Fluent nHibernate で構成されます。
セッションをフラッシュすると、2 秒以上かかります。
public void AddNewChild(LightPatientDto patient, LightPatientDto child)
{
var ePatient = this.Session.Load<Patient>(patient.Id);
var eChild = this.Session.Load<Patient>(child.Id);
switch (ePatient.Gender)
{
case Gender.Male:
eChild.Father = ePatient;
break;
case Gender.Female:
eChild.Mother = ePatient;
break;
default:
Assert.FailOnEnumeration(eChild.Gender);
break;
}
this.Session.Update(eChild);
this.Session.Flush(); // <== takes more than 2 seconds
}
NHibernate プロファイラーは、この SQL が 2008 ミリ秒で実行されることを示しています。SQLite 管理ツールを使用してこの SQL をコピー ペーストすると、90 ミリ秒で実行されます。
UPDATE Patient
SET BirthDate = '1964-05-06T00:00:00.00' /* @p0 */,
Fee = 0 /* @p1 */,
Height = 0 /* @p2 */,
InscriptionDate = '2007-05-21T00:00:00.00' /* @p3 */,
PlaceOfBirth = 'xxxxxx' /* @p4 */,
PrivateMail = '' /* @p5 */,
PrivateMobile = NULL /* @p6 */,
PrivatePhone = '0496/xx.xx.xx' /* @p7 */,
Reason = 'diabète' /* @p8 */,
Father_id = 2 /* @p9 */,
Insurance_id = 1 /* @p10 */,
Mother_id = NULL /* @p11 */,
Practice_id = 1 /* @p12 */,
Profession_id = NULL /* @p13 */,
Reputation_id = 1 /* @p14 */
WHERE Person_id = 3 /* @p15 */
実行時間を最適化するにはどうすればよいですか?
編集1
@csanchez が示唆したように、エンティティに動的更新を追加することに成功しました。SQL を NH Profiler で調べていると、次のようになります。
UPDATE Patient
SET Father_id = 2 /* @p0 */
WHERE Person_id = 21 /* @p1 */
これは非常に最適化されています!しかし、実行時間は…1852ms o_O
デバッガーでは、時間がかかるトランザクションをコミットしていることがわかります...なぜそんなに遅いのかわかりません...
編集2
各患者には、バイト配列としてテーブルに格納されている医療写真があります。テーブル作成用の SQL は次のとおりです (Fluent nHibernate によって実行されます)。
CREATE TABLE Picture (
Id integer PRIMARY KEY AUTOINCREMENT,
Bitmap blob,
Creation datetime,
LastUpdate datetime,
Notes text,
IsImported bool,
Tag_id bigint,
Patient_id bigint,
ThumbnailBitmap blob,
/* Foreign keys */
FOREIGN KEY (Patient_id)
REFERENCES Patient(),
FOREIGN KEY (Tag_id)
REFERENCES "Tag"()
);
でデータをドロップしDELETE Picture
てアプリケーションを再起動すると、更新は非常に高速です。
nHibernate はスマートになろうとして、すべてを遅くするようなことをしているようです。ただし、このコードで純粋な SQL クエリを実行すると、更新に 1 秒以上かかります。
using (var tx = this.Session.BeginTransaction())
{
var sql = "UPDATE Patient SET Father_id = 2 WHERE Person_id = 21";
var query = this.Session.CreateSQLQuery(sql);
query.ExecuteUpdate();
tx.Commit();
}