4

私はレガシーデータベースでFluentnHibernateを使用しており、メインのPersonテーブルとPersonに関する追加情報を含むいくつかの拡張テーブルがあります。これらの拡張テーブルは1対1です。つまり、拡張テーブルには1つの行しかなく、拡張テーブルは常に1人にマップする必要があります。

テーブル: Person
列: PersonID、FirstName、LastNameなど。

テーブル: PersonLogin
列: PersonID(FK、一意)、UserName、Passwordなど。

私のマッピングは次のように定義されています(無関係なプロパティは省略されています):

public PersonMap()
{
   Table("Person");
   Id(x => x.Id, "PersonID").Not.Nullable();
   References(x => x.Login, "PersonID").LazyLoad();
}

public LoginMap()
{
   Table("PersonLogin");
   Id(x => x.Id, "PersonID").GeneratedBy.Foreign("Person");
   References(x => x.Person, "PersonID").LazyLoad();
}

これは、両方のテーブルにデータがある場合に機能しますが、最近、一部の拡張テーブルにすべてのPerson行のデータがないことを知りました。これにより、クエリ中にエラーが発生しました。そこで、.NotFound.Ignore()PersonMapに追加して、次のようにしました。

   References(x => x.Login, "PersonID").LazyLoad().NotFound.Ignore();

これにより、ビジネスレイヤーが拡張テーブルの値を投影する必要がない場合、https://nhibernate.jira.com/browse/NH-1001が原因で、ログインテーブルから不要な選択を取得することになりました。一部の検索クエリでパフォーマンスがひどくなる原因になっています。

私はたくさんの投稿を精査しましたが、このシナリオに対処する方法についての確固たる答えは見つかりませんでした。以下は私が試したオプションです:


オプション1:

拡張テーブルに行を作成して、拡張テーブルに行のない人がいないことを確認してから、を削除し.NotFound.Ignore()ます。

このオプションの問題は、これがレガシーデータベースであり、Personが挿入されたときにPersonLoginが確実に挿入されるようにどこを更新する必要があるかわからないことです。


オプション2:

PersonMapからPersonLogin参照を削除し、Personクラス内にカスタムロードします。このような:

public class Person
{
    /// <summary> Gets or sets the PersonID </summary>
    public virtual int Id { get; set; }

    private bool loadedLogin;
    private PersonLogin login;
    public virtual PersonLogin Login
    {
        get
        {
            if (!loadedLogin)
            {
                login = SessionManager.Session().Get<PersonLogin>(Id);
                loadedLogin = true;
            }

            return login;
        }
        set
        {
             login = value;
             loadedLogin = true;
        }
    }
}

私が抱えている問題は、クエリを実行して多数のPersonオブジェクトとそのログインをプルバックするときにデータを熱心にフェッチできないことです。


オプション3:

これらのオブジェクトの例外をスローしないようにカスタムIEntityNotFoundDelegateを作成できるかどうかを確認するために、プレイを開始しました。

private class CustomEntityNotFoundDelegate : IEntityNotFoundDelegate
{
    public void HandleEntityNotFound(string entityName, object id)
    {
        if (entityName == "my.namespace.PersonLogin")
        {
            return;
        }
        else
        {
            throw new ObjectNotFoundException(id, entityName);
        }
    }
}

そして、これを構成に追加しました

cfg.EntityNotFoundDelegate = new CustomEntityNotFoundDelegate();

それは私のシナリオをキャッチし、エラーをスローする代わりに今すぐ戻りますが、これらのPersonLoginプロパティをビジネスオブジェクトに投影しようとすると、Proxyオブジェクトを使用しようとして、このエラーをスローします。クリーンに処理できます(おそらくIPostLoadEventListenerで)。

System.Reflection.TargetException occurred
Message = Non-static method requires a target
4

1 に答える 1

2

を維持することで、これが機能するようになったと思います.NotFound.Ignore()

私は最初に述べました:

これにより、ビジネスレイヤーが拡張テーブルの値を投影する必要がない場合、https://nhibernate.jira.com/browse/NH-1001が原因で、ログインテーブルから不要な選択を取得することになりました。一部の検索クエリでパフォーマンスがひどくなる原因になっています。

LINQクエリを微調整して、場合によってはIQueryOverを使用し、他のシナリオではLINQの使用を改善して、必要な値のみを投影することができました。これにより、プロジェクションで値が必要なかったため、拡張テーブルをプルバックするクエリが解決されたようです。

私のクエリはこれらの拡張テーブルを投影していないと思いましたが、IDとNameフィールドをいくつかの関連プロパティと連結するために投影で使用しているメソッドToKeyValuePairがあることがわかりました。LINQは拡張テーブルに結合せずに必要なフィールドが存在することを判別できなかったため、このメソッドはオブジェクトを完全にロードしていました。

于 2013-03-22T20:59:44.147 に答える