3

我被认为是 NHibernate 的新手。我希望我的 Article 实体类有两个惰性属性。其中一个是用户,另一个是内容。我的实体和映射就像

<class name="Article" table="TBL_ARTICLE">
    <id name="Id" column="ART_ID">
        <generator class="native" />
    </id>
    <property name="UserId" column="USR_ID" not-null="true" />
    <many-to-one name="User" column="USR_ID" insert="false" update="false" />
    <property name="Content" column="ART_CONTENT" not-null="true" lazy="true" />
</class>

public class Article
{
    public virtual long Id { get; set; }
    public virtual long UserId { get; set; }
    public virtual User User { get; set; }
    public virtual string Content { get; set; }
}

我选择它喜欢

using(ISession session = sessionFactory.OpenSession()) {
     return session.Query<Article>()
                   .SingleOrDefault(a => a.Id == id);
}

它工作正常。当我尝试访问 using 块之外的 User 或 Content 属性时,我得到了某种延迟加载异常。这是我所期待的。

在某些情况下,我喜欢急切地获取用户数据。我像这样选择它:

using(ISession session = sessionFactory.OpenSession()) {
     return session.Query<Article>()
                   .Fetch(a => a.User)
                   .SingleOrDefault(a => a.Id == id);
}

它仍然可以正常工作。当我尝试访问 using 块之外的 User 属性时,我可以获得其属性值,但是当尝试访问 Content 属性时,我仍然会遇到某种延迟加载异常,这仍然是我所期望的。

当我想获取内容数据时

using(ISession session = sessionFactory.OpenSession()) {
     return session.Query<Article>()
                   .Fetch(a => a.Content)
                   .SingleOrDefault(a => a.Id == id);
}

我得到一个例外:

Invalid join: a.Content
[.SingleOrDefault[Repository.NH.Article](.Fetch[Repository.NH.Article,System.String]
(NHibernate.Linq.NhQueryable`1[Repository.NH.Article], Quote((a, ) => (a.Content)), ),
Quote((a, ) => (Equal(a.Id, 1))), )]

我阅读了一些关于 HQL 执行此操作的博客文章,但我正在寻找使用 Linq Provider 的解决方案。

4

3 回答 3

1

Fetch构造仅适用于映射对象之间关系的属性,因此使用“引用”、“多对一”或“多对多”映射的属性。

这就是为什么它可以按预期使用该User属性而不是针对字符串Content属性的原因。

经过进一步调查,我认为您无法使用 LINQ 语法实现您想要的,但应该可以使用HQL使用提示的等效语句fetch all properties

session.CreateQuery("from Article fetch all properties")
于 2013-06-04T14:01:12.290 回答
0

正如其他人所解释的,引用和惰性标量属性的行为不同,LINQFetch方法只对前者有用。

您的问题有三种可能的解决方案:

  • 正如 CSL 建议的那样,当您需要急切地加载惰性属性时,请使用 HQL 而不是 LINQ。
  • 不要使用惰性属性,并在显示列表而不是获取完整实体时使用投影。
  • 修复您的实际问题,这是您的会话范围。当您仍在使用实体时,它应该始终可用。
于 2013-06-04T16:33:47.687 回答
0

您通常在引用类型上使用延迟,例如导致 SQL 中的连接的事物。由于 Content 是一个字符串,并且与对象图处于完全相同的级别,因此您所做的事情实际上并没有多大意义。发生的事情是当您尝试在 nhibernate 会话之外引用 Objects 字符串属性时,它会引发错误。另一方面,您无法获取非引用类型,因此您的问题。但是,您可以做一些不同的事情。如果您需要使用 Lazy 内容提取对象,请在您的休眠会话范围内使用 Query,如果您希望立即提取内容,请使用_session.Get<Article>(id); Get 将从数据库中加载完整的对象图。

于 2013-06-04T14:49:00.163 回答