可以直接在NHibernate中设置引用的外键吗?

可以直接在NHibernate中设置引用的外键吗?,nhibernate,fluent-nhibernate,dimensional-modeling,Nhibernate,Fluent Nhibernate,Dimensional Modeling,获得了一个项目,该项目以XML文件的形式从特定系统收集数据,这些数据以web请求的形式传入,将其转换为实体模型,并将其填充到数据库中进行报告 本项目使用与此问题相关的以下软件: C 4.0/.Net 4 NHibernate 3.0最新版本在NuGet中提供 流利的NHibernate与NH3一起使用 假设我有这样一个实体: public class Incident : Entity { public virtual string OriginatorSite { get; s

获得了一个项目,该项目以XML文件的形式从特定系统收集数据,这些数据以web请求的形式传入,将其转换为实体模型,并将其填充到数据库中进行报告

本项目使用与此问题相关的以下软件:

C 4.0/.Net 4 NHibernate 3.0最新版本在NuGet中提供 流利的NHibernate与NH3一起使用 假设我有这样一个实体:

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);
    }
}
DateDimension表已经填充-我的系统从未真正在这里创建任何记录。这些数据是在实际使用之前生成的——系统中每个相关日期对应一行。这是我的系统的特点之一。它承诺每一天都会有一排。如果有人失踪,那将是一次灾难性的失败

你可能会问,如果你不熟悉三维建模,为什么要这样做,就像我两天前写这篇文章时那样

嗯,我会有很多关于每个日期的事件记录。所以DateDimension表将比Incident表小得多,并且允许我使用NHibernate LINQ做一些事情,否则这将很困难。例如这样的事情:

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; }
}
        var IncidentsPerWeekday = _incidentRepository
            .GroupBy(i => i.DateDimension.Weekday)
            .Select(g => new Tuple<int,int>(g.Key, g.Count()))
            .ToList();
给我一份小组名单,告诉我这些事件在工作日是如何分配的。当然,这里可以添加许多不同的维度,使我能够围绕一系列不同的参数透视报告,并创建有趣的报告

然而,这里有一个小麻烦,我们终于找到了真正的问题

DateDimension有一个主键,它基本上是以特定格式表示的日期。2011年4月30日,情况如下:

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; }
}
        var IncidentsPerWeekday = _incidentRepository
            .GroupBy(i => i.DateDimension.Weekday)
            .Select(g => new Tuple<int,int>(g.Key, g.Count()))
            .ToList();
20110430

这是通过使用NHibernate中的自定义IIIdentifierGenerator完成的。因为我们每个日期只有一个记录,在我看来,这是一个相当干净的方法

此外,这将是一种让新的事件实体知道其相关DateDimension的引用外键的快速方法。有些工厂可能知道我们从Incident.RegisterTime DateTime中提取了这个键,然后将它填充到DateDimension\u id列中

然而,这似乎是我找不到的方法。Incident.DateDimension正确地要求实体引用。这意味着我必须从数据库中加载,对吗?。在某些导入场景中,这可能会太慢,因为我需要在尽可能短的时间内将大量事件实体插入数据库

当然,对于这个特定的示例,我可能可以在每次插入实体时执行一些自定义SQL,并允许空引用。这并不理想,但可以奏效

但是,有没有一种方法可以直接指定DateDimension引用的外键,而不是使用对实际存储的引用对象的引用来设置它

那肯定会使我摆脱一个巨大的头痛


提前感谢您的任何见解

这不是100%肯定的,但您可以尝试设置对具有适当Id的DateDimension类的新实例的引用。这假设事件和DateDimension之间没有任何级联,我猜这是正确的假设,因为DateDimension在您的数据模型中可能是不可变的


或者,您可以在映射中公开FK列,并直接设置它。

您可以使用ISession.Load方法来完成此操作

myIncident.DateDimension = mySession.Load("20110430");

这将为DateDimension创建一个代理,从而避免数据库跳闸。如果您访问代理上的密钥以外的任何属性,它将被加载。

您好,谢谢您的反馈!这听起来像是可行的,我投票通过了,但我还是选择了Jamie Ide提供的解决方案,因为我觉得这似乎更干净。谢谢你@当然是了,我完全忘记了加载。Ayende也有同样的场景,谢谢你的链接,我记得现在读到了。。Ayende的文章是在4月30日发表的,也是我问题中使用的例子,这是不是很奇怪。。。因为今天是我的生日,所以我选择了哪一天?也许不会,但我还是会把《暮光之城》的音乐排成队。再次感谢!:根据NHibernate Profiler,这就成功了!谢谢