【问题标题】:Mapping references to companion objects with fluent-nhibernate使用 fluent-nhibernate 映射对伴随对象的引用
【发布时间】:2010-08-19 09:27:34
【问题描述】:

我的 MVC 网站帐户具有以下基本域模型:

public class Account
{
    public Account()
    { 
        Details = new AccountDetails( this ); 
        Logon = new LogonDetails(this); 
    }
    public virtual int Id { get; private set; }
    public virtual AccountDetails Details { get; set; }
    public virtual LogonDetails Logon { get; set; }
    ...
}

public class AccountDetails
{
    // Primary Key
    public virtual Account Account { get; set; }
    public virtual DateTime Created { get; set; }
    ...
}

public class LogonDetails
{
    // Primary Key
    public virtual Account Account { get; set; }
    public virtual DateTime? LastLogon { get; set; }
    ...
}

AccountDetails 和 LogonDetails 都使用如下映射:

public class AccountDetailsOverride : IAutoMappingOverride<AccountDetails>
{
    public void Override( AutoMap<AccountDetails> mapping )
    {
        mapping
            .UseCompositeId()
            .WithKeyReference( x => x.Account, "AccountId" );

        mapping.IgnoreProperty( x => x.Account );
    }
}       

我已将帐户详细信息和登录详细信息拆分为单独的模型,因为我很少需要这些信息,而我需要用户 ID 和名称来进行许多站点操作和授权。我希望仅在需要时才延迟加载 Details 和 Logon 属性。通过我当前的映射尝试,我可以获得以下两种行为之一:

#1 创建表并加载成功,无法保存

使用此映射:

public class AutoOverride : IAutoMappingOverride<Account>
{
    public void Override( AutoMap<Account> mapping )
    {
        mapping.LazyLoad();
        mapping
            .References( x => x.Details )
            .WithColumns( x => x.Account.Id )
            .Cascade.All();
        mapping
            .References( x => x.Logon  )
            .WithColumns( x => x.Account.Id )
            .Cascade.All();
    }
}

表格按预期生成。现有数据正确加载到模型中,但我无法保存。相反,我得到了一个超出范围异常的索引。大概是因为 Account.Details 和 Account.Logon 都试图使用相同的 db 字段作为参考(Account.Id 本身)。

#2 表格包含额外字段,无法正确保存

使用此映射:

public class AutoOverride : IAutoMappingOverride<Account>
{
    public void Override( AutoMap<Account> mapping )
    {
        mapping.LazyLoad();
        mapping
            .References( x => x.Details )
            .Cascade.All();
        mapping
            .References( x => x.Logon  )
            .Cascade.All();
    }
}

我得到一个表,其中 Details_id 和 Logon_id 有一个单独的字段,但它们为空,因为在持久化帐户时 Details.Account.Id 的值为空。因此,尝试 Session.Get 帐户会导致 Details 和 Logon 为空。如果我保存帐户两次,表格会正确更新,我可以加载它。

帮助...

必须有一种映射这种层次结构的方法,我缺少一些简单的东西。有没有办法帮助 nhibernate 选择正确的字段(解决#1)或让它在保存后自动更新依赖字段(解决#2)?

感谢大家提供的任何见解。

【问题讨论】:

    标签: c# nhibernate


    【解决方案1】:

    如果我了解您的模型和期望的行为,那么您所拥有的实际上是AccountAccountDetails 之间以及AccountLogonDetails 之间的一对一关系。 References 创建多对一关系,这可能是您的问题;试试HasOne

    也就是说,出于这个和其他原因,除非绝对必要,否则我会避免一对一。可能比您展示的要多,但是为了避免加载两个 DateTime 字段,是否值得头疼和丑陋的模型?

    最后,由于我还没有测试过这个功能,所以这有点猜测,NHibernate 2.1(FNH 已切换为支持的版本)映射 XML 模式为property 元素定义了一个lazy 属性。 FNH 的 1.0 版本(应该在接下来的一两周内)将支持设置此属性。正如我所说,我尚未对其进行测试,但似乎这将允许您延迟加载正是您想要的各个属性。

    【讨论】:

    • 谢谢斯图尔特。我应该提到我已经尝试了一对一的映射,结果是所有三个类的整个集合都加入并加载了 Get。即使将 Logon 和 Details 属性指定为惰性也不能阻止这种情况。实际的详细信息类包含更多字段,因此值得付出努力。
    • 我进行了一些挖掘,看起来 NH 存在一些延迟加载一对一的问题,因为它对它们施加了限制,而且看起来列级延迟加载仍在等待实现,因为出色地。 FWIW,关于惰性属性的 JIRA 票的帖子建议将子类映射到同一个表并延迟加载子类......可能值得一试。 nhjira.koah.net/browse/…
    猜你喜欢
    • 2011-10-26
    • 2010-12-07
    • 2011-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-28
    相关资源
    最近更新 更多