【问题标题】:NHibernate LINQ and Many to Many MappingNHibernate LINQ 和多对多映射
【发布时间】:2012-07-18 07:50:53
【问题描述】:

我在 NHibernate 3.2 上使用 FluentNHibernate 1.3 映射了这些类:

public class ClassA
{
    public virtual Int32 Id{ get; }
    ....
    public ICollection<ClassB> ClassesB { get; }
    public ICollection<ClassC> ClassesC { get; }
}

public class ClassB
{
    public virtual Int32 Id{ get; }
    ....
    public ICollection<ClassA> ClassesA { get; }
    public ICollection<ClassC> ClassesC { get; }
}

public class ClassC
{
    public virtual Int32 Id{ get; }
    ....
    public ICollection<ClassA> ClassesA { get; }
    public ICollection<ClassB> ClassesB { get; }
}

所有映射都按预期正常工作。但是我需要使用 LINQ 进行查询,例如返回给定 ClassB 或 ClassA 实例中的所有 ClassC 实例,反之亦然。在获取 ClassC 列表之前,我需要在不加载任何 ClassB 或 ClassA 实例的情况下执行此操作,只需使用实例 ID 进行查询。

我知道我可以加载,例如,一个 ClassB 实例,然后获取 ClassesC 集合,但是对于我的应用程序设计,我必须这样做而不这样做,我将使用它来执行诸如在网格上分页之类的事情,以及与分页不同的其他操作。

在纯 SQL 上,我可以使用简单的连接查询来做到这一点,但我不知道如何使用 LINQ 来做到这一点。而且我不想要 HQL 或 ICriteria 的选项,它必须使用 LINQ(首选扩展)来完成,因为应用程序使用的插件必须不知道 NHibernate 的存在。该插件接收一个 IQueryable 实例来进行查询(这使我们能够轻松地将核心应用程序移植到其他数据库模式,例如 NoSQL 或其他东西,甚至无需重新编译插件或应用程序的其他部分)。

提前感谢您的帮助。

【问题讨论】:

  • 顺便说一句,使用 IQueryableLinq2nHibrenate 可能会非常棘手。在向插件提供IQueryable 之前,您必须三思而后行。
  • 我使用 NHibernate 3.2 并且它具有 LINQ“集成”,我将它用于其他“正常”查询而没有任何问题。插件是为一个非常封闭的系统开发的,所有的插件都是由内部程序员开发的,应用程序只能由同一个“公司”使用,不打算供公众使用。这些插件将主要用于报告和文件生成。相信我,我向他们发出了关于这种方法的所有警告,但我的客户认为一定是这样,呵呵呵呵呵呵。
  • 我只是将他们要求的内容告诉他们四个,我尽我所能警告他们(我什至有一封由 CEO 签名的信,以防万一,呵呵)。非常感谢您对此提出的建议。
  • Linq2nHibernateIQueryable 一起使用时可能会出现问题的示例之一:q.Where(sameName =&gt; …).Where(sameName =&gt; …) — 使用相同的变量名 sameName 可能会以无意义的异常破坏您的查询。以下是一些通用文章:[IQueryable is Tight Coupling](blog.ploeh.dk/2012/03/26/IQueryableIsTightCoupling.aspx) 和IQueryable Can Kill Your Dog, Steal Your Wife, Kill Your Will To Live, etc.

标签: linq nhibernate fluent-nhibernate fluent-nhibernate-mapping


【解决方案1】:

默认情况下,FluentNHibernate 中的 HasMany 会延迟加载集合。您可以使用流利的语法进行配置。

延迟加载示例:

class ClassAMap : ClassMap<ClassA>
{
    public ClassAMap()
    {
    // ...
    // lazy loading using select
    HasMany(x => x.ClassesB)
        .LazyLoad()
        .Fetch.Select()
    // ...
}

或使用join进行贪婪加载:

class ClassAMap : ClassMap<ClassA>
{
    public ClassAMap()
    {
    // ...
    // greedy loading using join
    HasMany(x => x.ClassesB)
        .Fetch.Join()
    // ...
}

conventions

Table.Is(x => x.EntityType.Name + "Table")
    DefaultLazy.Always()

无论如何,这个配置主题相当复杂,取决于您如何准确地配置映射。 我建议您使用log4net 查看 hHibernate SQL 日志以查看 SQL 命令是由 ORM 生成的

【讨论】:

  • 非常感谢Akim,您的快速答复!!!我也知道延迟加载的内容以及获取映射和约定,但是我需要它使用 IQueryable 接口来做到这一点,我需要使用映射类的其他字段进行查询。例如: Session.Query().Where(inst => inst.ClassC.Id == XXX && inst.ProcessStatus == ProcessStatusEnum.Pending).OrderBy........ 类似的东西。
  • 应该可以的。只需在您的日志文件中检查 ORM 生成的 SQL 并调整映射。你会有很多惊喜;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-12
  • 2011-12-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-29
相关资源
最近更新 更多