【发布时间】:2015-06-09 22:35:23
【问题描述】:
我试图找出为什么即使在急切加载集合并且生成的 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();
}
}
和 PricingIncrement 映射
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; }
}
我正在尝试查询所有具有特定 PricingIncrement 的 optionprice 值的 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 时,查询执行且结果正确,我从与 OptionIdentifier 匹配的可用 4 行中为 OptionPrice 表中与条件匹配的每个子项获取一行,在我的情况下为在 PricingIncrement 中有 4 行,在 OptionPrice 中有 4 行,对于 OptionIdentifier_id 的每个 PricingIncrement 一个 7)
但是当我尝试迭代集合以获取一些值时,由于某种原因,nhibernate 正在加载子集合,就好像指定了延迟加载一样,并加载了完整的 4 个子行。阅读文档 FetchMode 应该可以解决这个问题,防止 nhibernate 延迟加载子集合。类似于 N+1 常见问题。
我检查了 SQL Profiler 以查看发生了什么,当我尝试访问它时,nhibernate 正在生成没有原始过滤器的查询来填充子集合。如果我不访问该集合,则不会生成任何查询。
做一些测试,我尝试了不同的连接类型和获取模式,到目前为止,在不休眠加载所有元素的情况下迭代集合的唯一方法是在连接类型 LeftOuterJoin 中指定,但这意味着不同。
我试图搜索类似的问题,但他们都说急切加载应该可以工作,或者提到我应该使用过滤器。到目前为止,我还没有找到任何答案。
非常感谢任何帮助。
【问题讨论】:
标签: c# nhibernate nhibernate-criteria