0

イテレータを使用する NHibernate で読み取り専用プロパティをマップすることは可能ですか (つまり、yield return)?

たとえばPerson、読み取り専用IEnumerable<Cat> Catsプロパティを持つクラスとGetNextCat()、シーケンス内の次の猫を取得するメソッドが呼び出されたとします。

可能なマッピングは次のとおりです。

public class PersonMap : ClassMap<Person>
{
    public PersonMap()
    {
        HasMany(x => x.Cats).Access.ReadOnly(); // also tried .AsSet() and .AsBag()
    }
}

そして、IEnumerable<Cat> Catsプロパティの 2 つの可能な実装を次に示します。

// fails: 
//   System.InvalidCastException: Unable to cast object of type '<get_Cats>d__0' to 
//   type 'System.Collections.Generic.ICollection`1[MyProject.Cat]'.
public virtual IEnumerable<Cat> Cats
{
    get
    {
        var cat = GetNextCat();

        while(cat != null)
        {
            yield return cat;
            cat = GetNextCat();
        }

        yield break;
    }
}

// works
public virtual IEnumerable<Cat> Cats
{
    get
    {
        var catList = new List<Cat>();
        var cat = GetNextCat();

        while(cat != null)
        {
            catList.Add(cat);
            cat = GetNextCat();
        }

        return catList;
    }
}

プロパティの両方のバージョンで同じ結果が生成されます。では、NHibernate が最初の例では機能しないのに、2 番目の例では機能するのはなぜでしょうか? NHibernate が からコンパイラによって生成されたクラスを処理するように設定されていないということyield returnですか? それとも、これは Fluent だけの問題ですか?

4

1 に答える 1

1

プロパティの結果は異なります。

1 つ目は生成された IEnumerable (反復子) を生成し、2 つ目は生成されたリストを返します。NHibernate は、ICollection/ISet/Ilist (AsBag/Set/List に依存) を persistentBag/Set/List にラップしようとしますが、IEnumerable では失敗し、List では成功します。

ただし、NHibernate は生成されたオブジェクトをオンザフライで追跡できないため、2 番目のコードは実行されますが、途方もない結果や例外が発生するという点で、どちらも正しくありません。

結論:このプロパティはコードで生成され、データベースからロードされないため、マップしないでください。GetNextCat()次の猫を取得するために永続データが使用するロード/マップ。

于 2013-07-26T07:25:05.003 に答える