Fluent NHibernate - 如何将外键列映射为属性
Posted
技术标签:
【中文标题】Fluent NHibernate - 如何将外键列映射为属性【英文标题】:Fluent NHibernate - How to map the foreign key column as a property 【发布时间】:2009-04-01 23:16:39 【问题描述】:我确信这是一个直截了当的问题,但请考虑以下问题: 我在公司和部门之间有如下参考:
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;
好的。我想要的是我去后要填充的 Company 对象的 SectorID:
(new Company()).Sector = new Sector() Name="asdf"
然后冲洗一下。
我正在使用的映射在 Company 表中的数据库中创建了一个名为 Sector_Id 的附加列,但这不能作为 Company 的属性使用。我想要填充 SectorID 属性。
我目前在 CompanyMap 中使用的映射是
References(c => c.Sector).Cascade.All();
有人有什么想法吗?
感谢您的回复。
可悲的是,如果我执行第二个选项(将列的列名设置为与属性相同,或者设置 Map(x => x.SectorID, "Sector_Id")
,那么我会收到错误消息:
System.IndexOutOfRangeException:此 SqlParameterCollection 的索引 7 无效,Count=7。
我可能必须做第一个选项,但我担心当您调用 SectorID get 时会触发一个额外的查询,因为它将 Sector 本身从数据库中取出(除非它是急切加载的,这有点麻烦)。
我很惊讶没有一个简单的答案。
哇! 如果我使用
public virtual Guid SectorID
get return Sector.ID;
然后 nhibernate 足够聪明,知道组织查询中的 Sector_id 列实际上与 Sector.ID 相同,并且它在后台返回它。即使您延迟加载,它也不会发送额外的查询。我印象深刻!
作为后续......似乎休眠并不是真正编写能够映射对象中的外键列。尽管这在 Web 前端可能有点痛苦,但它是有道理的,因为这实际上是一个持久性问题,而不是真正的对象问题。 我正在使用 asp.net MVC 并编写了一个自定义模型绑定器,它将采用名称联系人(而不是 ContactID)的输入框,使用 texbox 中的 ID 新建一个新联系人,然后将其应用于模型的属性。这解决了 Web 前端下拉列表的问题。如果有人感兴趣,将发布代码。
【问题讨论】:
【参考方案1】:这很容易通过公式属性完成。
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();
【讨论】:
我给你积分来解决我遇到的错误,但这似乎完全不直观。如果 NHibernate 无法处理同时具有 FK ID 和关联的对象实例作为属性的常见场景,这似乎是一个设计问题。【参考方案2】:史蒂夫,你不需要 POCO 类中的 ForeignKey 属性。
例如,如果您将尝试获取文章作者的 ID,则不会执行连接选择。
var authorID = Article.Author.ID
【讨论】:
【参考方案3】:两个想法:首先,这样的事情不会实现你想要的吗?
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 => x.SectorID, "Sector_Id")”)?
【讨论】:
以上是关于Fluent NHibernate - 如何将外键列映射为属性的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Fluent 设置 NHibernate.Burrow?