Fluent NHibernate - 如何将外键列映射为属性

9 nhibernate fluent-nhibernate

我确信这是一个直截了当的问题,但请考虑以下内容:我在公司和部门之间有如下参考:

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; }
}
Run Code Online (Sandbox Code Playgroud)

好.我想要的是在我去之后要填充的Company对象的SectorID:

(new Company()).Sector = new Sector() { Name="asdf" }
Run Code Online (Sandbox Code Playgroud)

并做一个同花顺.

我正在使用的映射在Company表中名为Sector_Id的数据库中创建了一个额外的列,但这不是公司的属性.我想要填充SectorID属性.

我目前在CompanyMap中使用的映射是

References(c => c.Sector).Cascade.All();
Run Code Online (Sandbox Code Playgroud)

有没有人有任何想法?


感谢您的答复.遗憾的是,如果我执行第二个选项(将列的列名设置为与属性相同,或设置Map(x => x.SectorID, "Sector_Id")然后我得到错误:

System.IndexOutOfRangeException:此SqlParameterCollection的索引7无效,Count = 7.

我可能必须做第一个选项,但我担心当你调用SectorID get时会触发一个额外的查询,因为它将扇区本身从数据库中取出(除非它是急切加载的,这有点麻烦).

我很惊讶没有一个简单的答案.


哇!如果我使用

public virtual Guid SectorID
{
    get { return Sector.ID;
}   
Run Code Online (Sandbox Code Playgroud)

然后nhibernate很聪明地知道组织查询中的Sector_id列实际上与Sector.ID相同,并且它在引擎盖下返回.即使您延迟加载,它也不会发送额外的查询.我很佩服!


作为后续行动......似乎hibernate并不是真正编写为能够映射对象中的外键列.虽然这可能是网络前端的一个痛点,但这是有道理的,因为这实际上是一个持久性问题而不是真正的对象关注.我正在使用asp.net MVC并编写了一个自定义模型绑定器,它将采用名为Contact(而不是ContactID)的输入框,新建一个带有texbox内容ID的新联系人,然后将其应用于模型的属性.这解决了Web前端下拉列表的问题.如果有人有兴趣,请发布代码.

Jar*_*yer 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]");
  }    
}
Run Code Online (Sandbox Code Playgroud)

这应该完全符合你的要求.当Company是新的时,SectorId将为null; 当Company从DB中取出时,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();
}
Run Code Online (Sandbox Code Playgroud)


Chr*_*fer 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 }; }
    }
}
Run Code Online (Sandbox Code Playgroud)

其次,当您说映射在数据库中创建了一个名为 Sector_Id 的列时,这是除了您创建的名为 SectorID 的列之外吗?如果是这样,您可以更改列名称,以便它使用正确的名称(这是映射的文档,请参阅“指定列名称”下面的几个标题)。

另外,您是否映射 SectorID 属性(例如“Map(x => x.SectorID, "Sector_Id")”)?