【发布时间】:2017-01-27 16:56:33
【问题描述】:
在 NHibernate 中,如果一个实体被一个查询延迟加载,然后在同一会话中被第二个查询请求急切加载,则第二个查询中返回的类型始终是代理(我相信缓存的第一个查询的代理)。这可以在这个高度简化的英国示例中得到证明:
public class CarClassMap : ClassMap<Car>
{
public CarClassMap()
{
this.Id(x => x.Id);
this.Map(x => x.Model);
// note: lazy load by default
this.References(x => x.Colour).Column("ColourId").LazyLoad();
}
}
public class ColourClassMap : ClassMap<Colour>
{
public ColourClassMap()
{
this.Id(x => x.Id);
this.Map(x => x.Description);
}
}
public static void Main()
{
using (var session = CreateSessionFactory().OpenSession())
{
// note: both cars are the same colour in the database
var jaguar = session.QueryOver<Car>()
.Where(x => x.Id == 1)
.FutureValue()
.Value;
Console.WriteLine("Jaguar colour type=" + jaguar.Colour.GetType());
var aston =
session.QueryOver<Car>()
.Fetch(x => x.Colour).Eager //note: eager load
.Where(x => x.Id == 2)
.FutureValue()
.Value;
Console.WriteLine("Aston Martin colour type=" + aston.Colour.GetType());
}
Console.Read();
}
这个程序的输出是:
Jaguar colour type=ColourProxy
Aston Martin colour type=ColourProxy
两个“颜色”属性都是代理,尽管第二个查询请求急切加载。然而,当运行 just 急切加载查询时:
public static void Main()
{
using (var session = CreateSessionFactory().OpenSession())
{
var aston =
session.QueryOver<Car>()
.Fetch(x => x.Colour).Eager
.Where(x => x.Id == 2)
.FutureValue()
.Value;
Console.WriteLine("Aston Martin colour type=" + aston.Colour.GetType());
}
Console.Read();
}
输出是:
Aston Martin colour type=TestApp.Colour
具体的底层类型。
在我们的真实系统中,返回的对象被传递给执行一些复杂逻辑的映射层。这种差异给我们带来了问题,因为属性的类型不同,具体取决于之前在 Session 中发出的查询。
基本上,问题是我们如何避免请求急切加载导致代理,而是将其强制为具体类型?我们知道我们可以使用 NHibernate 实用程序手动“取消代理”对象,但我们宁愿不必在每次查询该实体时都这样做。如果可能的话,我们更喜欢在类映射中做到这一点。还是有更好的解决方案?谢谢。
【问题讨论】:
标签: c# nhibernate fluent-nhibernate