我的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属性。通过我当前的映射尝试,我可以获得以下两种行为之一:
使用此映射:
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本身)。
使用此映射:
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)?
感谢大家提供的任何见解。
答案 0 :(得分:0)
如果我理解您的模型和期望的行为,那么您所拥有的实际上是Account
和AccountDetails
之间以及Account
和{{1}之间的一对一关系}。 LogonDetails
创建了多对一关系,这可能是你的问题;请尝试References
。
那说,出于这个原因和其他原因,除非绝对必要,否则我会避免一对一。可能不仅仅是你展示的内容,但是为了避免加载两个HasOne
字段,是否值得头痛和丑陋的模型呢?
最后,这有点推测,因为我还没有测试过这个功能,NHibernate 2.1(FNH已经转换为支持的版本)映射XML模式为DateTime
元素定义了lazy
属性。 FNH的1.0版本(应在下周或两周内)将支持设置此属性。正如我所说,我还没有测试过它,但似乎这会让你懒得加载各个属性,这正是你想要的。