是否可以在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的一个问题?
答案 0 :(得分:1)
属性的结果是截然不同的。
第一个产生生成的IEnumerable(迭代器),secod返回生成的列表。 NHibernate尝试将一个ICOLlection / ISet / Ilist(取决于AsBag / Set / List)包装在persistentBag / Set / List中,该类对于IEnumerable失败并且对List成功。
然而两者都不正确,因为NHibernate无法在动态生成的对象上更改跟踪,因此第二个代码将运行但会产生疯狂的结果和异常。
结论:根本不会映射此属性,因为它是在代码中生成的,而不是从数据库加载的。加载/映射持久性数据GetNextCat()
用于获取下一只猫。