我看到NHibernate在迭代一个有点深的对象图时抛出一个LazyInitializationException。我假设我对NHibernate的工作方式存在误解;你能解释我哪里出错吗?
public class CustomerSummary {
public virtual ISet<House> Houses { get; set; } = new HashSet<House>()
}
public class House {
public virtual ISet<Feed> Feeds { get; set; } = new HashSet<Feed>()
}
public class Feed {
public virtual int Id { get; set; }
public virtual int OtherId { get; set; }
public virtual DateTime Date { get; set; }
public virtual ISet<Charge> Charges { get; set; } = new HashSet<Charge>()
}
public class Charge {
public virtual int Id { get; set; }
public virtual int OtherId { get; set; }
public virtual decimal Amount { get; set; }
}
public IEnumerable<CustomerSummary> GetAll()
{
CustomerSummary cs = null;
House h = null;
Feed f = null;
var query = Session.QueryOver(() => cs)
.JoinAlias(() => cs.Houses, () => h, JoinType.LeftOuterJoin)
.JoinAlias(() => h.Feeds, () => f, JoinType.LeftOuterJoin,
Restrictions.Eq(nameof(Feed.Date), month));
var results = query.TransformUsing(Transformers.DistinctRootEntity)
.Future();
return results;
}
public void GenerateInvoices()
{
var summaries = m_Repository.GetAll();
foreach (var summary in summaries) {
foreach (var house in summary.Houses) {
foreach (var feed in house.Feeds) {
//Exception here on Charges iterator, but only on the 2nd CustomerSummary entity.
foreach (var charge in feed.Charges) {
}
}
}
}
}
在NHibernate Profiler中,我可以看到第二个会话被创建导致LazyInitializationException:
如果您需要信息,我会更新问题。提前感谢您的回答!
我包括我怀疑可能导致问题的相关映射。请注意用于将2个表连接在一起的 OtherId ,而不是主键。不同的CustomerSummaries或Houses可能会引用相同的Charge实体。
public class FeedMap : ClassMap<Feed> {
public FeedMap()
{
Id(x => x.Id).Column("Feed_Id");
Map(x => x.Date).Column("Feed_Date");
Map(x => x.OtherId).Column("Other_Id");
References(x => x.House).Column("House_Id");
HasMany(x => x.Charges)
.PropertyRef(nameof(Charge.OtherId))
.KeyColumn("Other_Id");
}
}
添加Repository / SessionContext的实现。
我通过Fluent NHibernate配置Context,如下所示:
.ExposeConfiguration(x => x.SetProperty("current_session_context_class", "thread_static"));
和...
public abstract class Repository {
protected ISessionFactory SessionFactory { get; }
protected ISession Session {
get {
if (CurrentSessionContext.HasBind(SessionFactory)) {
return SessionFactory.GetCurrentSession();
}
var session = SessionFactory.OpenSession();
session.FlushMode = FlushMode.Never;
var stackTrace = new StackTrace();
var frames = stackTrace.GetFrames();
var sessionName = stackTrace.GetFrame(1).GetMethod().Name;
if (frames != null) {
foreach (var frame in frames) {
if (frame.GetMethod().Module.Assembly.GetName().Name != Assembly.GetExecutingAssembly().GetName().Name) {
sessionName = frame.GetMethod().Name;
break;
}
}
}
HibernatingRhinos.Profiler.Appender.NHibernate.NHibernateProfiler.RenameSessionInProfiler(session, sessionName);
CurrentSessionContext.Bind(session);
return session;
}
}
protected Repository(ISessionFactory sessionFactory)
{
if (sessionFactory == null) {
throw new ArgumentNullException(nameof(sessionFactory));
}
SessionFactory = sessionFactory;
}
}