【问题标题】:How use of select for associations in linq to NHibernate如何在 linq to NHibernate 中使用 select 进行关联
【发布时间】:2012-11-01 14:33:05
【问题描述】:

我有一个由 NHibernate 实现的应用程序。我的项目有一个Person 类:

public class Person : RootEntityBase
{    
    virtual public string FirstName { get; set; }
    virtual public string LastName { get; set; }
    virtual public string FatherName { get; set; }

    virtual public IList<Asset> Assets { get; set; }
    virtual public IList<PersonPicture> PersonPictures { get; set; }
}

通过这个映射:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Domain" namespace="Domain.Entities">
  <class name="Person" table="Person_Person" >

    <id name="Id">
      <generator class="native" />
    </id>

    <property name="FirstName" not-null="true"/>

    <property name="LastName" not-null="true"/>

    <property name="FatherName" not-null="true"/>

    <bag name="Assets" inverse="true" table="Person_Asset" cascade="all-delete-orphan" >
      <key column="Person_id_fk"/>
      <one-to-many class="Asset"/>
    </bag>

    <bag name="PersonPictures" inverse="true" table="Person_PersonPicture" cascade="all-delete-orphan" >
      <key column="Person_id_fk"/>
      <one-to-many class="PersonPicture"/>
    </bag>

  </class>

我需要通过 linq 进行查询,其中包含对 Person 某些属性的选择。

var q = SessionInstance.Query<Person>()
               .Select(x => new Person(x.Id)
                                  {
                                      FirstName = x.FirstName,
                                      LastName = x.LastName,
                                      PersonPictures = x.PersonPictures //this line has error
                                  })
               .ToList();

通过添加PersonPictures 进行选择,此查询通过此消息出现运行时异常:

could not execute query\r\n[ select person0_.Id as col_0_0_, person0_.FirstName as col_1_0_, person0_.LastName as col_2_0_, ...

内部异常消息是:

Incorrect syntax near the keyword 'as'.

堆栈跟踪是:

   at NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters)
   at NHibernate.Loader.Loader.ListIgnoreQueryCache(ISessionImplementor session, QueryParameters queryParameters)
   at NHibernate.Loader.Loader.List(ISessionImplementor session, QueryParameters queryParameters, ISet`1 querySpaces, IType[] resultTypes)
   at NHibernate.Hql.Ast.ANTLR.Loader.QueryLoader.List(ISessionImplementor session, QueryParameters queryParameters)
   at NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.List(ISessionImplementor session, QueryParameters queryParameters)
   at NHibernate.Engine.Query.HQLQueryPlan.PerformList(QueryParameters queryParameters, ISessionImplementor session, IList results)
   at NHibernate.Impl.SessionImpl.List(IQueryExpression queryExpression, QueryParameters queryParameters, IList results)
   at NHibernate.Impl.AbstractSessionImpl.List(IQueryExpression queryExpression, QueryParameters parameters)
   at NHibernate.Impl.ExpressionQueryImpl.List()
   at NHibernate.Linq.NhQueryProvider.ExecuteQuery(NhLinqExpression nhLinqExpression, IQuery query, NhLinqExpression nhQuery)
   at NHibernate.Linq.NhQueryProvider.Execute(Expression expression)
   at NHibernate.Linq.NhQueryProvider.Execute[TResult](Expression expression)
   at Remotion.Data.Linq.QueryableBase`1.GetEnumerator()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)

我该怎么做?

【问题讨论】:

    标签: c# linq nhibernate select linq-to-nhibernate


    【解决方案1】:

    我不明白您为什么要进行以下查询:

    var q = SessionInstance.Query<Person>()
               .Select(x => new Person(x.Id)
                                  {
                                      FirstName = x.FirstName,
                                      LastName = x.LastName,
                                      PersonPictures = x.PersonPictures //this line has error
                                  })
               .ToList();
    

    映射和域类看起来正确。因此,您应该简单地继续以下操作:

    IList<Person> persons = (from p in SessionInstance.Query<Person>()
    select p).ToList();
    

    如果您想对图片应用过滤器:

    IList<Person> persons = (from p in SessionInstance.Query<Person>()
    select p
    where p.PersonPictures.Any(pp => pp.Property == [...]).ToList();
    

    无需重新映射每个属性,这是 NHibernate 映射 + NHibernate LINQ 提供程序的工作。

    【讨论】:

    • 我的Person 课程非常棒。它有许多属性和关联。您的解决方案等同于 SQL 中的select * from tblPersons。但是我需要选择 Person 类的一些属性和关联。
    【解决方案2】:

    您的映射是正确的。使用 Criteria API 时,我可以达到预期的效果。

    但是您所引用的问题是已知的并已报告: https://nhibernate.jira.com/browse/NH-2707

    但恐怕,不固定。 因此,如果您可以(在这种情况下)使用 Criteria:

    // example returning the complete list
    var query = session.CreateCriteria<Preson>().List<Person>(); 
    

    然后你可以继续:

    query.Select(x => new Person(x.Id)
    ...
    

    【讨论】:

      【解决方案3】:

      我不是 Linq To nHibernate ninja,但是下面的呢?

      var q = SessionInstance.Query<Person>().Fetch(p => p.PersonPictures).ToList();
      

      你需要做那个投影吗?我在回答中省略了它,但如果需要可以添加它。

      参考资料:

      Linq for NHibernate and fetch mode of eager loading

      Fetch vs FetchMany in NHibernate Linq provider

      http://mikehadlow.blogspot.co.nz/2010/08/nhibernate-linq-eager-fetching.html

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-09-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多