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

时间:2012-08-14 15:39:19

标签: c# fluent-nhibernate foreign-key-relationship 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; }
}

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

Ticket ticket = new Ticket() {
    Title = "Problem with MS Word",
    ServiceId = "Microsoft Word 2012"
};

我不想做的事情如下:

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

我确实有充分的理由,就像我说的那样可以在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");
    }
}

任何帮助总是受到赞赏!


只需快速编辑 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);
}

我不想注入 ServiceRepository 也只是为了获取对票证服务的引用。

2 个答案:

答案 0 :(得分:3)

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

一些可能的选择:

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

答案 1 :(得分:0)

你可以用一招。保持代码清洁。

像这是一个NH的问题,你必须在NH Repositories中实现它的解决方案,所以,我这样解决它。

在添加或更新

之前
if (!string.IsNullOrEmpty(ServiceId) && Service == null)
{
   Service = new Service{ Id = ServiceId };
}

正常的存储库工作......

我测试并工作。您的架构仍然没有ORM决策