我试图找出为什么在贪婪加载集合并且生成的SQL正确时,子集合会返回而没有进行过滤。
这些类的流畅映射如下:
public class OptionIdentifierMap : ClassMap<OptionIdentifier>
{
public OptionIdentifierMap()
: base("OptionIdentifier")
{
//Id Mapping Removed
HasMany<OptionPrice>(x => x.OptionPrices)
.KeyColumn("OptionIdentifier_id")
.Cascade.None();
}
}
public class OptionPriceMap : ClassMap<OptionPrice>
{
public OptionPriceMap()
: base("OptionPrice")
{
//Id Mapping removed
References(x => x.Option)
.Column("OptionIdentifier_id")
.Cascade.None()
.ForeignKey("FK_OptionPrice_OptionIdentifier_id_OptionIdentifier_Id")
.Not.Nullable();
References(x => x.Increment)
.Column("PricingIncrement_id")
.Cascade.None()
.ForeignKey("FK_OptionPrice_PricingIncrement_id_PricingIncrement_Id")
.Not.Nullable();
Map(x => x.Price).Not.Nullable();
}
}
和定价增量映射
public class PricingIncrementMap : ClassMap<PricingIncrement>
{
public PricingIncrementMap()
: base("PricingIncrement")
{
Map(x => x.IncrementYear);
HasMany<OptionPrice>(x => x.Options)
.KeyColumn("PricingIncrement_id")
.Cascade.None().Inverse();
}
}
实体包括:
public class PricingIncrement : Entity
{
public PricingIncrement()
{
Options = new List<OptionPrice>();
}
public virtual int IncrementYear { get; set; }
public virtual IList<OptionPrice> Options { get; set; }
}
public class OptionPrice : Entity
{
public OptionPrice()
{
}
public virtual OptionIdentifier Option { get; set; }
public virtual PricingIncrement Increment { get; set; }
public virtual float Price { get; set; }
}
public class OptionIdentifier : Entity
{
public OptionIdentifier()
{
OptionPrices = new List<OptionPrice>();
}
public virtual IList<OptionPrice> OptionPrices { get; set; }
}
我正在尝试查询特定定价增量的所有具有选项价格值的OptionIdentifier。Nhibernate从我的条件生成的SQL查询如下:
SELECT this_.Id as Id37_4_,
.......
FROM OptionIdentifier this_ inner join OptionPrice op2_ on this_.Id = op2_.OptionIdentifier_id
inner join PricingIncrement i3_ on op2_.PricingIncrement_id = i3_.Id
WHERE (this_.IsDeleted = 0)
and this_.Id in (7)
and i3_.IncrementYear = 2015
我用于构建此查询的标准是:
ICriteria pagedCriteria = this.Session.CreateCriteria<OptionIdentifier>()
.CreateAlias("OptionPrices", "op", JoinType.InnerJoin)
.CreateAlias("op.Increment", "i", JoinType.InnerJoin)
.SetFetchMode("op", FetchMode.Eager)
.SetFetchMode("i", FetchMode.Eager)
.Add(Restrictions.Eq("i.IncrementYear", 2015))
.Add(Expression.In("Id", idList.ToList<int>()))
.SetResultTransformer(CriteriaSpecification.DistinctRootEntity);
在查看 SQL Profiler 时,查询执行并且结果是正确的,对于与标准匹配的 OptionPrice 表中的每个子代都会得到一行,在我的情况下匹配的行数是1,因为有4行匹配了 OptionIdentifier(PricingIncrement 中有4行,OptionPrice 中也有4行,针对 Identifier_id 为7 的每个 PricingIncrement 有一个对应的 OptionPrice 行)。
但是当我尝试迭代集合以获取某些值时,出于某种原因 nhibernate 加载了子集合,就好像懒加载被指定一样,并加载了所有 4 个子行。阅读文档 FetchMode 应该可以解决这个问题,防止 nhibernate 懒加载子集合。类似于 N+1 常见问题。
我检查了 SQL Profiler 来查看发生了什么事情,当我尝试访问它时,nhibernate 生成没有原始过滤器的查询来填充子集合。如果我不访问集合,则不会生成任何查询。
进行一些测试后,我尝试了不同的连接类型和提取模式,到目前为止,唯一在不让 hibernate 加载所有元素的情况下迭代集合的方法是指定 LeftOuterJoin 的连接类型,但这意味着不同的东西。
我尝试搜索类似的问题,但它们都说急切加载应该起作用,或者提到我应该使用过滤器。到目前为止,我还没有找到任何答案。
非常感谢您的帮助。