3

ISession.Load が返すものと同様のオブジェクト プロキシを作成したいのですが、いくつかのフィールドが初期化されています。他のプロパティの場合、アクセスすると、プロキシはデータベースからオブジェクト全体を取得します。次の例を検討してください。

public class User
{
    protected User() {

    }

    public User(int id, string username, string email) {
        // ... 
    }

    // initialize the following fields from other datasources
    public virtual int Id { get; set; }
    public virtual string UserName { get; set; }
    public virtual string Email { get; set; }

    // the rest of fields when accessed will trigger a select by id in the database
    public virtual string Field1 { get; set; }
    public virtual string Field2 { get; set; }
    public virtual DateTime Field3 { get; set; }
    public virtual ISet<Comment> Comments { get; set; }
}

私の場合、Id、UserName、Email はよく知られているので、これらのフィールドを含むオブジェクト プロキシを作成し、他のフィールドについてはデフォルトのプロキシ動作のままにします。この ID がデータベースに見つからない場合に例外をスローするだけでなく、事前に初期化されたフィールドが一致しない場合、またはそれらをサイレントに上書きする場合に例外をスローすることもできます。プロキシ ファクトリに NHibernate.ByteCode.Castle を使用しています。

編集:これの目的は、他の場所でクエリできるエンティティからいくつかの投影プロパティを取得できるようにすること (たとえば、lucene インデックス)、およびデータベース呼び出しを回避することです。次に、これらのプロパティのサブセットのみを含むカスタム コンポーネント クラスでこれらのフィールドをラップする代わりに、プロキシ オブジェクトを直接使用して、必要に応じて残りのフィールドをロードできるようにします。最良のシナリオでは、データベースにまったくアクセスしませんが、いくつかのまれなケースでは、他のフィールドにもアクセスしたいと考えています。SELECT N+1 問題の影響は、バッチ処理を使用することで大幅に軽減できます。私が使用したい仮想バージョンのコードは次のようになります。

        // create User object proxy with some fields initialized
        var user = Session.Load<User>(5, new { UserName = "admin", Email = "admin@company.com" });
        Console.WriteLine(user.Id); // doesn't hit the database
        Console.WriteLine(user.UserName); // doesn't hit the database
        Console.WriteLine(user.FullName); // doesn't hit the database
        if (somecondition) {
            Console.WriteLine(user.Field1); // fetches all other fields 
        }
4

3 に答える 3

0

クエリ内で熱心なフェッチを指定して、必要な関連付けを実際に取得できます。これは、使用しているクエリ スタイル ( Criteria,Hql または LINQto NH ) に応じてさまざまな方法で実行できます。しかし、重要なのはフェッチモードを変更することです。

于 2011-06-14T12:53:10.763 に答える
0

コレクション以外のプロパティについては、私はそうしません。
エンティティをロードするときに DB からそれらをプリフェッチするコストは (通常) 非常に小さいので、気にする必要はありません。
コレクション プロパティの場合は、コレクション フェッチ戦略を としてマークするだけ'lazy=true'です。

そのようなことを考える唯一のケースは、必要のない非常に多くのプロパティがある場合です (例では、Field1..Field20 とします)。
その場合、次のいずれかを行います: 1. これらのプロパティをまとめてcomponent
として定義するか、 2. エンティティのプロパティのサブセットのみを取得するための DTO を作成します。

于 2011-06-14T13:34:06.163 に答える
-1

Field1プロパティ、Field2Field3、マッピングでlazy = "true" (または Fluent NHib の場合は Not.LazyLoad()) を指定するとComments役立つ場合がありますが、Select N+1 の問題については不明です。

もう 1 つの方法は、lazy = "false" を指定することですUserNameEmail

于 2011-06-14T13:13:46.557 に答える