我有一个项目和一个人(有点简化):
public class Project
{
public virtual Person CreatedBy { get; set; }
}
public class Person
{
public virtual string Username { get; set; }
}
我正在接受NH Linq的项目:
var projects = from p in session.Query<Project>()
select p;
var project = projects.First();
有时使用Fetch()
var project = projects.Fetch(p => p.CreatedBy).First();
现在,如何在单元测试中验证该项目.CreatedBy 不或 急切加载(反之),具体取决于Fetch()是否为用过的?根据我的理解,使用Fetch()应该急切加载Person,如果我不使用Fetch(),它应该延迟加载Person。
我试过
Assert.IsTrue(NHibernateUtil.IsInitialized(project.CreatedBy));
并且
NHibernateUtil.IsPropertyInitialized(project, "CreatedBy")
但无论我是否使用Fetch(),它们都返回true。 IsInitialized()适用于集合(一对多),例如Person.Projects,但不适用于多对一...
CreatedBy属性应该是延迟加载的,但有时我希望它被急切加载,我希望单元测试确认它正在按预期工作。
CreatedBy属性的映射是
<many-to-one name="CreatedBy" class="Person" fetch="select">
<column name="PERSON_ID" precision="10" scale="0" not-null="true" />
</many-to-one>
我验证了这样的映射:
var to1 = NHibernateConfiguration.GetClassMapping(typeof(Project))
.ReferenceablePropertyIterator.FirstOrDefault(p => p.Name == "CreatedBy")
.Value as NHibernate.Mapping.ToOne;
Assert.IsTrue(to1.IsLazy);
Assert.IsFalse(to1.UnwrapProxy);
哪个过去了。
有什么想法吗?
答案 0 :(得分:5)
如果NHibernateUtil.IsInitialized(project.CreatedBy)
返回true,那是因为它已初始化。
如果已经在会话中加载了Person,那么无论您是否急切地获取CreatedBy,它都将被初始化,这要归功于Identity Map。
答案 1 :(得分:-1)
我看到的一个解决方案如下:
而不是使用自动属性, 对于CreatedBy,使用'经典 property',它使用支持 字段,像这样:
private Person _createdBy;
public Person CreatedBy
{
get { return _createdBy; }
set { _createdBy = value; }
}
在映射文件中,指示NHibernate应使用支持字段,而不是属性:
<many-to-one name="CreatedBy" class="Person" access="field.camelcase-underscore" fetch="select">
<column name="PERSON_ID" precision="10" scale="0" not-null="true" />
</many-to-one>
然后,您可以做的最美妙的事情是在单元测试项目中创建一个扩展方法,检查_createdBy字段是否已初始化。
很遗憾,您无法使用扩展方法访问私有成员。
因此,我认为您可以在Project类上创建一个内部方法,用于检查_createdBy字段是否已初始化。
您还应该使用[InternalsVisibleTo][1]
属性,以便包含您的单元测试的项目可以访问Project
类中的内部方法。
public class Project
{
private Person _createdBy;
public Person CreatedBy
{
get{return _createdBy;}
set{ _createdBy = value; }
}
internal IsCreatedByInitialized()
{
return _createdBy != null;
}
}
在您的单元测试中,您可以这样做:
Assert.IsTrue (p.isCreatedByInitialized());
请注意,如果您的单元测试位于单独的项目中,则需要指明该程序集应该可以访问内部方法:
因此,在AssemblyInfo.cs
类所在的项目的Project
文件中,您应该这样做:
[InternalsVisibleTo ("MyTestProject")]