NHibernate Linq Provider渴望获取惰性字符串属性

时间:2013-06-04 13:51:01

标签: c# nhibernate lazy-loading eager-loading

我被认为是NHibernate的新手。我希望我的Article实体类有两个惰性属性。其中一个是User other is Content。我的实体和映射就像

<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的解决方案。

3 个答案:

答案 0 :(得分:1)

Fetch构造仅适用于映射对象之间关系的属性,因此使用“References”,“Many-To-One”或“Many-To-Many”映射的属性。

这就是为什么它按预期使用User属性而不是字符串Content属性。

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

session.CreateQuery("from Article fetch all properties")

答案 1 :(得分:0)

您通常在参考类型上使用Lazy,例如导致SQL加入的事情。由于内容是一个字符串,并且与对象图完全相同,因此您所做的事情并没有多大意义。发生的事情是当你尝试引用nhibernate会话之外的Objects字符串属性时,它会抛出错误。另一方面,您无法获取非引用类型,因此您的问题。但是,你可以做一些不同的事情。如果您需要使用Lazy内容拉出对象,请在您的nhibernate会话范围内使用查询,如果您希望急切地撤出内容,请使用_session.Get<Article>(id); Get将加载完整的对象图来自数据库。

答案 2 :(得分:0)

正如其他人所解释的那样,引用和惰性标量属性的行为不同,LINQ Fetch方法只适用于前者。

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

  • 当您需要急切加载延迟属性时,使用HQL而不是LINQ,如CSL建议的那样。
  • 不要使用延迟属性,并在显示列表时使用投影,而不是获取完整实体。
  • 修复您的实际问题,这是您的会话范围。当您仍在使用实体时,它应该始终可用。