NHibernate映射使用迭代器的readonly属性(yield return)

时间:2013-07-25 19:11:40

标签: c# nhibernate fluent-nhibernate

是否可以在NHibernate中映射使用迭代器的readonly属性(即,yield return)?

例如,假设我们有一个Person类,其中包含只读IEnumerable<Cat> Cats属性,另一个名为GetNextCat()的方法可以获取序列中的下一个cat。

以下是可能的映射:

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

以下是IEnumerable<Cat> Cats属性的两种可能实现:

// 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会破坏第一个例子,而第二个例子呢?是不是NHibernate没有设置来处理来自yield return的编译器生成的类?或者这只是Fluent的一个问题?

1 个答案:

答案 0 :(得分:1)

属性的结果是截然不同的。

第一个产生生成的IEnumerable(迭代器),secod返回生成的列表。 NHibernate尝试将一个ICOLlection / ISet / Ilist(取决于AsBag / Set / List)包装在persistentBag / Set / List中,该类对于IEnumerable失败并且对List成功。

然而两者都不正确,因为NHibernate无法在动态生成的对象上更改跟踪,因此第二个代码将运行但会产生疯狂的结果和异常。

结论:根本不会映射此属性,因为它是在代码中生成的,而不是从数据库加载的。加载/映射持久性数据GetNextCat()用于获取下一只猫。