特定のシステムからXMLファイルとしてデータを収集し(これらはWebリクエストとして受信されます)、それをエンティティモデルに変換し、レポート用にデータベースに詰め込むプロジェクトを取得しました。
プロジェクトでは、次のソフトウェアを使用しています(この質問に関連)。
- C#4.0 / .Net 4
- NHibernate 3.0(NuGetで利用可能な最新のもの)
- 流暢なNHibernate(NH 3と一緒に行くもの)
私がこのようなエンティティを持っているとしましょう(簡略化):
public class Incident : Entity
{
public virtual string OriginatorSite { get; set; }
public virtual string DestinationSite { get; set; }
public virtual IncidentType IncidentType { get; set; }
public virtual TimeSpan TotalWaitTime { get; set; }
public virtual TimeSpan TotalActionTime { get; set; }
public virtual DateTime RegisterTime { get; set; }
public virtual DateTime CloseTime { get; set; }
public virtual DateDimension DateDimension { get; set; }
}
そしてこれはこうしてマッピングされます:
public class IncidentMap : ClassMap<Incident>
{
public IncidentMap()
{
Id(c => c.Id);
Map(c => c.OriginatorSite);
Map(c => c.DestinationSite);
Map(c => c.IncidentType).CustomType<IncidentType>();
Map(c => c.TotalWaitTime);
Map(c => c.TotalActionTime);
Map(c => c.RegisterTime);
Map(c => c.CloseTime);
References<DateDimension>(c => c.DateDimension);
}
}
(IDはエンティティ基本クラスから取得されます)
そのようなことを扱う人はおそらくすでにコードから読んでいるので、私はここでいくつかの次元モデリングをしようとしています。私はこのテーマに不慣れで、おそらくDoing It Wrong(tm)ですが、少なくともこの方法からいくつかのメリットを得ることを望んでいます。各インシデントは、次のようなDateDimensionオブジェクトを参照します。
public class DateDimension : Entity
{
public virtual int DayOfMonth { get; set; }
public virtual int Weekday { get; set; }
public virtual string WeekdayName { get; set; }
public virtual int Week { get; set; }
public virtual int MonthPart { get; set; }
public virtual int Month { get; set; }
public virtual string MonthName { get; set; }
public virtual int Quarter { get; set; }
public virtual int Year { get; set; }
}
DateDimensionテーブルはすでに入力されています-私のシステムは実際にここにレコードを作成することはありません。これらは、実際に使用される前に生成されます。システム内の関連する日付ごとに1行です。それが私のシステムの特徴のひとつです。可能な日付ごとに1つの行が存在することを約束します。1つが欠落している場合、それは壊滅的な障害になります。
これを書いている2日前の私がそうであったように、なぜこれを行うのか、あなたが次元モデリングに不慣れであるかどうかを尋ねるかもしれません。
さて、私は各日付のインシデントレコードをたくさん持っています。したがって、DateDimensionテーブルはIncidentテーブルよりもはるかに小さくなり、NHibernateLINQで他の方法では困難なことを実行できるようになります。たとえば、次のようなものです。
var IncidentsPerWeekday = _incidentRepository
.GroupBy(i => i.DateDimension.Weekday)
.Select(g => new Tuple<int,int>(g.Key, g.Count()))
.ToList();
事件が平日の間でどのように分かれているかを教えてくれるグループのリストを教えてください。もちろん、ここに追加できるさまざまなディメンションがあり、さまざまなパラメーターを中心にレポートをピボットして、興味深いレポートを作成できます。
ただし、ちょっとした煩わしさが1つあり、ここでようやく本当の問題にたどり着きます。
DateDimensionには、基本的に特定の形式で表される日付である主キーがあります。2011年4月30日の場合、次のようになります。
20110430
これは、NHibernateのカスタムIIdentifierGeneratorを使用して行われます。日付ごとに1つのレコードしかないので、これは私の意見ではかなりクリーンな方法です。
また、新しいインシデントエンティティに関連するDateDimensionへの参照の外部キーを知らせる簡単な方法になります。一部のファクトリは、たとえばIncident.RegisterTime DateTimeからこのキーを抽出し、それをDateDimension_id列に詰め込むことを知っています。
しかし、これは私が行う方法を見つけることができないように思われることです。Incident.DateDimensionは、当然、エンティティ参照を要求します。つまり、データベースからロードする必要があります(右?)。これは、可能な限り短い時間で多くのインシデントエンティティをデータベースに挿入する必要がある特定のインポートシナリオでは遅すぎる可能性があります。
確かに、この特定の例では、エンティティを挿入するたびにカスタムSQLを実行し、NULL参照を許可することでこれを行うことができます。理想的ではありませんが、機能する可能性があります。
ただし、実際の保存された参照オブジェクトへの参照を設定する代わりに、DateDimension参照の外部キーを直接指定する方法はありますか?
それは確かに私に大きな頭痛を取り除くでしょう!
洞察を事前に感謝します!