使用fluent-nhibernate映射对伴随对象的引用

时间:2009-08-05 23:42:55

标签: c# nhibernate

我的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的值为null。因此,尝试Session.Get帐户导致详细信息和登录为空。如果我保存帐户两次,表格会正确更新,我可以加载它。

帮助...

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

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

1 个答案:

答案 0 :(得分:0)

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

那说,出于这个原因和其他原因,除非绝对必要,否则我会避免一对一。可能不仅仅是你展示的内容,但是为了避免加载两个HasOne字段,是否值得头痛和丑陋的模型呢?

最后,这有点推测,因为我还没有测试过这个功能,NHibernate 2.1(FNH已经转换为支持的版本)映射XML模式为DateTime元素定义了lazy属性。 FNH的1.0版本(应在下周或两周内)将支持设置此属性。正如我所说,我还没有测试过它,但似乎这会让你懒得加载各个属性,这正是你想要的。