NHibernate 搜索 N+1 期
我正在使用 NHibernate 搜索 NHibernate 3.0 GA。
我的产品存储库中有此代码:
public IList<Product> Find(string term)
{
var productFields = new[] { "Name", "Description" };
var importance = new Dictionary<String, float>(2) { { "Name", 4 }, { "Description", 1 } };
var analyzer = new StandardAnalyzer();
var parser = new MultiFieldQueryParser(
productFields,
analyzer,
importance);
var query = parser.Parse(term);
var session = Search.CreateFullTextSession(NHibernateSession.Current);
var tx = session.BeginTransaction();
var fullTextQuery = session.CreateFullTextQuery(query);
fullTextQuery.SetFirstResult(0).SetMaxResults(20);
var results = fullTextQuery.List<Product>();
tx.Commit();
return results;
}
在 NH Profiler 中,我可以看到为找到的每个产品发出了一条 select 语句。我缺少什么?
我发现了 2009 年的此帖子,但想必此错误已得到修复。
编辑[06/06/2011]:
就关联而言,我的属性映射如下:
mapping.HasManyToMany(c => c.Categories)
.Table("CatalogHierarchy")
.ParentKeyColumn("child_oid")
.ChildKeyColumn("oid")
.Cascade.None()
.Inverse()
.LazyLoad()
.AsSet();
mapping.HasMany(c => c.Variants)
.Table("CatalogProducts")
.Where("i_ClassType=2")
.KeyColumn("ParentOID")
.Cascade.SaveUpdate()
.AsSet();
我真的不想急于获取所有类别。
I'm using NHibernate Search for NHibernate 3.0 GA.
I have this code in my product repository:
public IList<Product> Find(string term)
{
var productFields = new[] { "Name", "Description" };
var importance = new Dictionary<String, float>(2) { { "Name", 4 }, { "Description", 1 } };
var analyzer = new StandardAnalyzer();
var parser = new MultiFieldQueryParser(
productFields,
analyzer,
importance);
var query = parser.Parse(term);
var session = Search.CreateFullTextSession(NHibernateSession.Current);
var tx = session.BeginTransaction();
var fullTextQuery = session.CreateFullTextQuery(query);
fullTextQuery.SetFirstResult(0).SetMaxResults(20);
var results = fullTextQuery.List<Product>();
tx.Commit();
return results;
}
In NH Profiler, I can see that a select statement is issued for every product found. What am I missing?
I found this thread from 2009 but presumably this bug has been fixed.
EDIT [06/06/2011]:
My property mappings as far as associations go are as follows:
mapping.HasManyToMany(c => c.Categories)
.Table("CatalogHierarchy")
.ParentKeyColumn("child_oid")
.ChildKeyColumn("oid")
.Cascade.None()
.Inverse()
.LazyLoad()
.AsSet();
mapping.HasMany(c => c.Variants)
.Table("CatalogProducts")
.Where("i_ClassType=2")
.KeyColumn("ParentOID")
.Cascade.SaveUpdate()
.AsSet();
I don't really want to eager fetch all categories.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
由于 NHibernate.Search 不稳定,我会直接从我的应用程序使用(而且我确实这样做了)Lucene.NET - 只是向 Lucene 询问对象的 Id,然后使用
Session.Load()
加载它。您还可以在类映射级别(而不是关系级别)更改 LazyLoad 设置。
希望有帮助。
编辑:您可以为关系指定批量大小,这样它们就不会导致选择 N+1 问题
As NHibernate.Search is unstable, I would use (and I did) Lucene.NET directly from my application - just to ask Lucene for objects' Ids and then load it using
Session.Load()
.Also you could change LazyLoad settings at class mapping level, not at relationship level.
Hope it helps.
EDIT: you could specify batch-size for relationships, so they wouldn't cause select N+1 problem
您是否引用此方法返回的产品列表中的任何延迟加载属性?如果是这样,您可以将属性映射更改为“eager fetch”。
Are you referencing any lazy loaded properties in the product list that is returned by this method? If so, you can change the property mapping to "eager fetch".
我最后解决了这个问题。我意识到我并没有将整个事情打包成一个交易。一旦我这样做了,N+1 问题就消失了。
小学生的错误,但是嘿,你从错误中学习。
I solved this in the end. I realised I had not wrapped the whole thing into a transaction. Once I did, the N+1 issue was gone.
Schoolboy error, but hey, you learn by your mistakes.