6

我正在寻找一种在两个实体之间添加关联并为外键设置可设置 ID 的方法。我已经搜索过以前的帖子,但我能找到的最接近的是 .Load 关联的建议——这不是我所希望的。我知道这可以通过 .HasForeignKey 绑定在实体框架中完成,但我似乎无法在 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 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也只是为了获取对Ticket的Service的引用。

4

2 回答 2

3

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

一些可能的选择:

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

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

于 2012-08-31T10:47:15.470 回答
0

你可以使用一个技巧。保持你的代码干净。

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

添加或更新之前

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

正常的存储库工作...

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

于 2012-10-28T10:38:57.230 回答