我确信这是一个简单的问题,但请考虑以下问题: 我在公司和部门之间有如下参考:
public class Company {
public Guid ID { get; set; }
public Sector Sector { get; set; }
public Guid SectorID { get; set; }
}
public class Sector {
public Guid ID { get; set; }
public string Name { get; set; }
}
确定。我想要的是在我去之后填充公司对象的SectorID:
(new Company()).Sector = new Sector() { Name="asdf" }
然后冲洗。
我正在使用的映射在Company表中名为Sector_Id的数据库中创建了一个附加列,但这不是公司的属性。我希望填充SectorID属性。
我目前在CompanyMap中使用的映射是
References(c => c.Sector).Cascade.All();
有没有人有任何想法?
感谢您的回复。
遗憾的是,如果我执行第二个选项(将列的列名设置为与属性相同,或设置Map(x => x.SectorID, "Sector_Id")
,则会出现错误:
System.IndexOutOfRangeException:此SqlParameterCollection的索引7无效,Count = 7.
我可能不得不做第一个选项,但我担心当你调用SectorID get时会触发一个额外的查询,因为它将扇区本身从数据库中取出(除非它是急切加载的,这有点像麻烦)。
我很惊讶没有一个简单的答案。
WOW! 如果我使用
public virtual Guid SectorID
{
get { return Sector.ID;
}
然后nhibernate足够聪明,知道组织查询中的Sector_id列实际上与Sector.ID相同,并且它在引擎盖下返回。即使您延迟加载,它也不会发送额外的查询。我印象深刻!
作为后续行动......似乎hibernate并没有真正编写为能够映射对象中的外键列。虽然这可能是网络前端的一个痛点,但这是有道理的,因为这实际上是一个持久性问题而不是真正的对象关注。 我正在使用asp.net MVC并编写了一个自定义模型绑定器,它将采用名为Contact(而不是ContactID)的输入框,新建一个带有texbox内容ID的新联系人,然后将其应用于模型的属性。这解决了Web前端下拉列表的问题。如果有人有兴趣,我会发布代码。
答案 0 :(得分:13)
使用公式属性可以轻松完成。
public class Company {
public virtual Guid Id { get; set; }
public virtual Guid? SectorId { get; set; }
public virtual Sector Sector { get; set; }
}
public class CompanyMap : ClassMap<Company> {
public CompanyMap() {
Id(x => x.Id); // Maps to a column named "Id"
References(x => x.Sector); // Maps to a column named "Sector_id", unless you change the NHibernate default mapping rules.
Map(x => x.SectorId).Formula("[Sector_id]");
}
}
这应该按照你想要的方式行事。当Company
为新的时,SectorId
将为空;从数据库中提取Company
时,将使用给定的公式值填充SectorId
。 SectorId
作为属性公开,这使得它非常适合处理Web下拉等。当您保存时,您仍然需要绑定“真实”关联。假设在表单中选择了SectorId
...
using (var txn = session.BeginTransaction()) {
// Set the FK reference.
company.Sector = session.Load<Sector>(company.SectorId);
// Save the new record.
session.Save(company);
// Commit the transaction.
txn.Commit();
}
答案 1 :(得分:2)
两个想法:首先,这样的事情不会达到你想要的效果吗?
public class Company {
public Guid ID { get; set; }
public Sector Sector { get; set; }
public Guid SectorID {
get { return Section.ID; }
// Really not sure what behavior your setter should have here; Maybe it shouldn't even have one?
set { Sector = new Sector { ID = value }; }
}
}
其次,当你说映射在名为Sector_Id的数据库中创建了一个列时,除了你创建的名为SectorID的列之外还有吗?如果是这样,您可以更改列名,使其使用正确的名称(here's the documentation for mappings,请参阅“指定列名称”中的几个标题。)。
另外,您是否映射了SectorID属性(例如“Map(x =&gt; x.SectorID,”Sector_Id“)”)?
答案 2 :(得分:2)
Steve你不需要在POCO类中使用ForeignKey属性。
例如,如果您尝试获取文章作者的ID,则不会执行加入选择。
var authorID = Article.Author.ID