3

私はNHibernateの初心者と見なされています。Article エンティティ クラスに 2 つの遅延プロパティを持たせたいと考えています。そのうちの 1 つはユーザーで、もう 1 つはコンテンツです。私のエンティティとマッピングは

<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 プロバイダーを使用したソリューションを探しています。

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

通常、SQL で Join を引き起こすものなど、参照型には Lazy を使用します。Content は文字列であり、オブジェクト グラフとまったく同じレベルにあるため、実際に行っていることはあまり意味がありません。nhibernate セッションの外で Objects 文字列プロパティを参照しようとすると、エラーが発生します。一方、非参照型をフェッチすることはできないため、問題が発生します。ただし、少し違うことを行うこともできます。オブジェクトを Lazy コンテンツで引き出す必要がある場合は、nhibernate セッションのスコープ内でクエリを使用します。コンテンツを積極的に引き出す必要がある場合は、_session.Get<Article>(id); Get を使用して、データベースから完全なオブジェクト グラフを読み込みます。

于 2013-06-04T14:49:00.163 に答える
0

他の人が説明したように、参照と遅延スカラー プロパティの動作は異なり、LINQFetchメソッドは前者にのみ適しています。

この問題には、次の 3 つの解決策が考えられます。

  • 遅延プロパティを熱心にロードする必要がある場合は、CSL が提案したように、LINQ の代わりに HQL を使用してください。
  • 怠惰なプロパティを使用しないでください。完全なエンティティをフェッチする代わりに、リストを表示するときにプロジェクションを使用してください。
  • セッションの範囲である実際の問題を修正します。エンティティを使用している間は、いつでも利用できるはずです。
于 2013-06-04T16:33:47.687 に答える