NHibernate:在映射中使用 base class 时避免 N+1 问题
NHibernate: Avoid N+1 Issues when base class is used in Mapping
我有以下场景:
Session
class 有很多 ProcessableItem
和一个 SqlTask
来自 ProcessableItem
class。
一个SqlTask
可以有很多变量(属性SqlTaskInputParameters
、SqlParameterVariable
class;有些任务没有变量)。
重点在Session
class ProcessableItem
(不是任务本身)用作导航 属性:
public class Session
{
[DataMember]
public virtual IList<ProcessableItem> ProcessableItems
{
get { return this._items; }
set { this._items = value; }
}
}
public SessionMap()
{
HasMany(t => t.ProcessableItems)
}
public class ProcessableItem
{
...
}
public class SqlTask : ProcessableItem
{
[DataMember]
public virtual IList<SqlParameterVariable> SqlTaskInputParameters { get; set; };
}
所以在这种情况下,基础 class ProcessableItem
用作导航 属性 我想提前加载 SqlTask
的变量对象以避免n+1 个问题。
这是我的代码,但我如何访问派生的特定属性 SqlTask
(如 SqlTaskInputParameters
):
var query = session.Query<ETLSession>()
.Where(s => s.Id == request.IdETLSession);
query.FetchMany(s => s.ProcessableItems)
.ThenFetch(p => p.ChildsOnSuccess).ToFuture();
Session session = query.ToFuture().ToList().First();
您不能急切加载派生的关系 class。
在你的情况下你甚至不应该,因为你似乎已经在获取另一个集合(ChildsOnSuccess
),并且在这里获取另一个集合会导致它们之间的笛卡尔积,导致你的结果重复. (这是 NHibernate 的限制。)
好消息是,除了急切获取之外,还有其他方法可以解决 N+1 问题。
- 保持延迟加载但启用 batching of lazy loads. I have put some detailed explanation here on Stack Overflow.
- 使用second level cache。但是好吧,那是缓存,所以最好从另一个开始,如果您稍后添加二级缓存,无论如何它仍然是有益的。
我有以下场景:
Session
class 有很多 ProcessableItem
和一个 SqlTask
来自 ProcessableItem
class。
一个SqlTask
可以有很多变量(属性SqlTaskInputParameters
、SqlParameterVariable
class;有些任务没有变量)。
重点在Session
class ProcessableItem
(不是任务本身)用作导航 属性:
public class Session
{
[DataMember]
public virtual IList<ProcessableItem> ProcessableItems
{
get { return this._items; }
set { this._items = value; }
}
}
public SessionMap()
{
HasMany(t => t.ProcessableItems)
}
public class ProcessableItem
{
...
}
public class SqlTask : ProcessableItem
{
[DataMember]
public virtual IList<SqlParameterVariable> SqlTaskInputParameters { get; set; };
}
所以在这种情况下,基础 class ProcessableItem
用作导航 属性 我想提前加载 SqlTask
的变量对象以避免n+1 个问题。
这是我的代码,但我如何访问派生的特定属性 SqlTask
(如 SqlTaskInputParameters
):
var query = session.Query<ETLSession>()
.Where(s => s.Id == request.IdETLSession);
query.FetchMany(s => s.ProcessableItems)
.ThenFetch(p => p.ChildsOnSuccess).ToFuture();
Session session = query.ToFuture().ToList().First();
您不能急切加载派生的关系 class。
在你的情况下你甚至不应该,因为你似乎已经在获取另一个集合(ChildsOnSuccess
),并且在这里获取另一个集合会导致它们之间的笛卡尔积,导致你的结果重复. (这是 NHibernate 的限制。)
好消息是,除了急切获取之外,还有其他方法可以解决 N+1 问题。
- 保持延迟加载但启用 batching of lazy loads. I have put some detailed explanation here on Stack Overflow.
- 使用second level cache。但是好吧,那是缓存,所以最好从另一个开始,如果您稍后添加二级缓存,无论如何它仍然是有益的。