有一个项目从特定系统以 XML 文件的形式收集数据(这些以 Web 请求的形式出现),将其转换为实体模型,并将其填充到数据库中以进行报告。
该项目使用以下软件(与此问题相关):
- C# 4.0 / .Net 4
- NHibernate 3.0(NuGet 中的最新版本)
- Fluent 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来自Entity基类)
由于处理此类事情的人可能已经阅读了代码,因此我正在尝试在这里进行一些维度建模。我是这个主题的新手,很可能做错了(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 表已填充 - 我的系统从未真正在此处创建任何记录。这些是在实际使用之前生成的——系统中每个相关日期都有一行。这是我系统的功能之一。它承诺每个可能的日期都会有一行。如果缺少一个,那将是一场灾难性的失败。
为什么这样做,你可能会问,如果你是维度建模的新手,就像我在两天前写这篇文章时那样。
好吧,每个日期我都会有很多事件记录。因此,DateDimension 表将比 Incident 表小很多,并且允许我使用 NHibernate LINQ 来完成原本会很困难的事情。例如这样的:
var IncidentsPerWeekday = _incidentRepository
.GroupBy(i => i.DateDimension.Weekday)
.Select(g => new Tuple<int,int>(g.Key, g.Count()))
.ToList();
给我一个小组列表,告诉我这些事件是如何在工作日中划分的。当然,这里可以添加许多不同的维度,让我可以围绕一组不同的参数旋转报告并创建有趣的报告。
然而,有一个小烦恼,在这里我们终于到达了真正的问题。
DateDimension 有一个主键,它基本上是它以特定格式表示的日期。2011 年 4 月 30 日,它看起来像这样:
20110430
这是通过在 NHibernate 中使用自定义 IIdentifierGenerator 来完成的。由于我们每个日期只有一条记录,因此在我看来,这是一种相当干净的方法。
此外,这将是一种让新事件实体知道对其相关 DateDimension 的引用的外键的快速方法。一些工厂会知道我们从 Incident.RegisterTime DateTime 中提取此密钥,然后将其填充到 DateDimension_id 列中。
但是,这是我似乎无法找到的方法。Incident.DateDimension 理所当然地需要实体引用。这意味着我必须从数据库中加载它(对吗?)。在某些导入场景中,这可能太慢了,我需要在尽可能短的时间内将大量事件实体插入数据库。
当然,对于这个特定的示例,我可以通过在每次插入实体时执行一些自定义 SQL 来执行此操作,并允许 NULL 引用。这并不理想,但它可以工作。
但是,有没有办法直接指定 DateDimension 引用的外键,而不是使用对真实存储引用对象的引用来设置它?
那肯定会让我摆脱一个巨大的头痛!
提前感谢您的任何见解!