流畅的NHibernate - 将外键映射为属性

Pau*_*ann 6 c# foreign-key-relationship fluent-nhibernate fluent-nhibernate-mapping

我正在寻找一种方法来添加两个实体之间的关联,并具有外键的可设置ID.我搜索过以前的帖子,但我能找到的最接近的建议是.加入协会 - 这不是我所希望的.我知道这可以在带有.HasForeignKey绑定的Entity Framework中完成,但我似乎无法在Fluent NHibernate中找到一种方法.

以两个示例实体为例:

public class Ticket
{
    public virtual int Id { get; set; }
    public virtual string Title { get; set; }
    public virtual string ServiceId { get; set; }
    public virtual Service Service { get; set; }
}

public class Service
{
    public virtual string Id { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我希望能够创建Ticket的新实例并使用以下方法为其分配服务(假设表中已存在关联的服务):

Ticket ticket = new Ticket() {
    Title = "Problem with MS Word",
    ServiceId = "Microsoft Word 2012"
};
Run Code Online (Sandbox Code Playgroud)

我不想做的是以下内容:

Ticket ticket = new Ticket() {
    Title = "Problem with MS Word",
    Service = Session.Load<Service>("Microsoft Word 2012")
};
Run Code Online (Sandbox Code Playgroud)

我确实有充分的理由,就像我说过这可以在Entity Framework中完成,但我真的很难过如何在Fluent NHibernate中实现同样的东西.我的映射目前看起来像这样:

public class TicketMapping : ClassMap<Ticket>
{
    public TicketMapping()
    {
        Id(m => m.Id);
        Map(m => m.Title).Column("Title");
        Map(m => m.ServiceId).Column("ServiceId");
        HasOne(m => m.Service).ForeignKey("ServiceId");

        Schema("dbo");
        Table("Tickets");
    }
}

public class ServiceMapping : ClassMap<Service>
{
    public ServiceMapping()
    {
        Id(m => m.Id);

        Schema("dbo");
        Table("Services");
    }
}
Run Code Online (Sandbox Code Playgroud)

任何帮助总是赞赏!


只是对Jay的快速编辑- 我不想Session.Load我的元素的原因是因为我不希望我的表示层(MVC 3)知道NHibernate的任何事情 - 因此我使用存储库模式并注入单个存储库进入控制器.因此,例如,我将拥有一个符合以下合同的TicketRepository

public interface IRepository<T>
{
    T GetById(object id);
    void Create(T entity);
    void Update(T entity);
    void Delete(T entity);
}
Run Code Online (Sandbox Code Playgroud)

我不想只是为了获得对Ticket服务的引用而注入ServiceRepository.

Try*_*gve 3

在我看来,在使用 NHibernate 时,你无法真正避免使用 Session.Load(id)。正如评论中提到的,这不会访问数据库,只是创建一个带有 id 的代理对象。

一些可能的选择:

  1. 将第二个通用存储库 (ServiceRepository) 注入控制器。我真的看不出有什么问题,但出于某种原因你想避免它。您可以将 LoadById 方法添加到通用接口,并在 NH 和 EF(或其他)的每个实现中以不同的方式实现该方法。在 EF impl 中,该方法可能像 GetById 一样工作,而在 NH impl 中,它调用 Session.Load
  2. 为 AR(聚合根)实现一个非通用存储库,在本例中为 Ticket。这可能有加载服务和票证的特定方法。
  3. 在两个存储库之上实现另一个抽象,并将其注入控制器而不是选项 1 中的两个存储库。这可能是一个持久性无知的 UnitOfWork,如下所述:持久性无知的 UoW,或某种编排的应用程序服务创建 Tickets 或 TicketFactory。

在这 3 个选项中,选项 1 可能是最简单的,而选项 3 可能会提供更好的抽象和更高的可维护性。