nhibernate查询优化
我有这个查询:
var resQuery = (from pan in session.Query<Pan>()
orderby pan.AdnMonture.Marque.Nom select pan).ToList<Pan>();
Pan 对象引用了其他几个对象:
<many-to-one name="TypeMonture" column="IDType_Monture" cascade="save-update" not-null="true" />
<many-to-one name="AgeMonture" column="IDAge_Monture" cascade="save-update" not-null="true" />
<many-to-one name="SexeMonture" column="IDSexe_Monture" cascade="save-update" not-null="true" />
<many-to-one name="NatureMonture" column="IDNature_Monture" cascade="save-update" not-null="true" />
<many-to-one name="MatiereVerre" column="IDMatiere_Verre" cascade="save-update" />
<many-to-one name="TypeCouleurVerre" column="IDType_Couleur_Verre" cascade="save-update" />
<many-to-one name="CouleurVerre" column="IDCouleur_Verre" cascade="save-update" />
<many-to-one name="ClasseVerre" column="IDClasse_Verre" cascade="save-update" />
<many-to-one name="MontageMonture" column="IDMontage_Monture" cascade="save-update" not-null="true" />
<many-to-one name="BaseMonture" column="IDBase_Monture" cascade="save-update" not-null="true" />
<many-to-one name="CharniereMonture" column="IDCharniere_Monture" cascade="save-update" />
<many-to-one name="BrancheFormeMonture" column="IDBranche_Forme_Monture" cascade="save-update" />
<many-to-one name="BrancheEpaisseurMonture" column="IDBranche_Epaisseur_Monture" cascade="save-update" />
<many-to-one name="TenonPositionMonture" column="IDTenon_Position_Monture" cascade="save-update" not-null="true" />
<many-to-one name="TenonTailleMonture" column="IDTenon_Taille_Monture" cascade="save-update" not-null="true" />
<many-to-one name="FormeMonture" column="IDForme_Monture" cascade="save-update" not-null="true" />
有时我需要获得每个项目的值,例如:
foreach (var pan in resQuery)
{
var test = pan.TypeMonture.Name
// and more ...
}
我有时在该查询中得到大约 100 个结果,并且对于这个单页我可以有大约 1k 个查询。 有什么解决方案可以避免这种情况吗? (存储过程除外)
问候
编辑
Mathieu 解决方案有效,但我简化了示例的情况。 我有这个错误:
A fetch request must be a simple member access expression of the kind o => o.Related; 'pan.Adn.Fabricant' is too complex.
Nom du paramètre : relatedObjectSelector
我的 Pan 对象引用了 Adn 对象。
<many-to-one name="AdnMonture" column="IDADN_Mont" cascade="save-update" not-null="true" />
这个 Adn 对象引用了我之前提供的所有数据。 (参见之前的 hbm.xml)
这种情况还有其他解决方案吗? 也许与加入?
编辑2
我尝试使用ThenFetch
return (from pan in session.Query<PanierMonture>()
.Fetch(pan => pan.AdnMonture)
.ThenFetch(adn => adn.Fabricant)
.ThenFetch(adn => adn.Reference)
.ThenFetch(adn => adn.Marque)
orderby pan.AdnMonture.Marque.Nom
select pan).ToList<PanierMonture>();
第一个ThenFirst 作品 但第二个被情报阻止了。 我使用 Fabricant 对象。 所以我尝试了一下:
return (from pan in session.Query<PanierMonture>()
.Fetch(pan => pan.AdnMonture)
.ThenFetch(adn => adn.Fabricant)
.Then(adn => adn.Reference)
.Then(adn => adn.Marque)
orderby pan.AdnMonture.Marque.Nom
select pan).ToList<PanierMonture>();
但还是不行。 intellisense 不给我 adn 对象
我找到了这个解决方法:
return (from pan in session.Query<PanierMonture>()
.Fetch(pan => pan.AdnMonture)
.ThenFetch(adn => adn.Fabricant)
.Fetch(pan => pan.AdnMonture)
.ThenFetch(adn => adn.Marque)
.Fetch(pan => pan.AdnMonture)
.ThenFetch(adn => adn.Reference)
.Fetch(pan => pan.AdnMonture)
.ThenFetch(adn => adn.Coloris)
.Fetch(pan => pan.AdnMonture)
.ThenFetch(adn => adn.TailleMonture)
orderby pan.AdnMonture.Marque.Nom
select pan).ToList<PanierMonture>();
正确吗? 生成的sql查询有点奇怪:
select ..... from Panier_Monture paniermont0_ left outer join ADN_Monture adnmonture1_ on paniermont0_.IDADN_Mont=adnmonture1_.IDADN_Monture left outer join Fabricant fabricant2_ on adnmonture1_.IDFabricant=fabricant2_.IDFabricant left outer join ADN_Monture adnmonture3_ on paniermont0_.IDADN_Mont=adnmonture3_.IDADN_Monture left outer join Marque marque4_ on adnmonture3_.IDMarque=marque4_.IDMarque left outer join ADN_Monture adnmonture5_ on paniermont0_.IDADN_Mont=adnmonture5_.IDADN_Monture left outer join Reference reference6_ on adnmonture5_.IDReference=reference6_.IDReference left outer join ADN_Monture adnmonture7_ on paniermont0_.IDADN_Mont=adnmonture7_.IDADN_Monture left outer join Coloris coloris8_ on adnmonture7_.IDColoris=coloris8_.IDColoris left outer join ADN_Monture adnmonture9_ on paniermont0_.IDADN_Mont=adnmonture9_.IDADN_Monture left outer join Taille_Monture taillemont10_ on adnmonture9_.IDTaille=taillemont10_.IDTaille left outer join ADN_Monture adnmonture11_ on paniermont0_.IDADN_Mont=adnmonture11_.IDADN_Monture left outer join Marque marque12_ on adnmonture11_.IDMarque=marque12_.IDMarque order by marque12_.Nom asc
表AdnMonture每次都重复? 有没有可能出现问题?
问候并再次感谢
I've this query :
var resQuery = (from pan in session.Query<Pan>()
orderby pan.AdnMonture.Marque.Nom select pan).ToList<Pan>();
The Pan object reference several other object :
<many-to-one name="TypeMonture" column="IDType_Monture" cascade="save-update" not-null="true" />
<many-to-one name="AgeMonture" column="IDAge_Monture" cascade="save-update" not-null="true" />
<many-to-one name="SexeMonture" column="IDSexe_Monture" cascade="save-update" not-null="true" />
<many-to-one name="NatureMonture" column="IDNature_Monture" cascade="save-update" not-null="true" />
<many-to-one name="MatiereVerre" column="IDMatiere_Verre" cascade="save-update" />
<many-to-one name="TypeCouleurVerre" column="IDType_Couleur_Verre" cascade="save-update" />
<many-to-one name="CouleurVerre" column="IDCouleur_Verre" cascade="save-update" />
<many-to-one name="ClasseVerre" column="IDClasse_Verre" cascade="save-update" />
<many-to-one name="MontageMonture" column="IDMontage_Monture" cascade="save-update" not-null="true" />
<many-to-one name="BaseMonture" column="IDBase_Monture" cascade="save-update" not-null="true" />
<many-to-one name="CharniereMonture" column="IDCharniere_Monture" cascade="save-update" />
<many-to-one name="BrancheFormeMonture" column="IDBranche_Forme_Monture" cascade="save-update" />
<many-to-one name="BrancheEpaisseurMonture" column="IDBranche_Epaisseur_Monture" cascade="save-update" />
<many-to-one name="TenonPositionMonture" column="IDTenon_Position_Monture" cascade="save-update" not-null="true" />
<many-to-one name="TenonTailleMonture" column="IDTenon_Taille_Monture" cascade="save-update" not-null="true" />
<many-to-one name="FormeMonture" column="IDForme_Monture" cascade="save-update" not-null="true" />
And I need sometimes to have the value of each items, ex :
foreach (var pan in resQuery)
{
var test = pan.TypeMonture.Name
// and more ...
}
I've sometimes about 100 result in that query, and I can have about 1k query for this single page.
Is there any solution to avoid that ? (other than stored procedure)
Regards
Edit
The Mathieu solution worked but I simplified the case for the example.
And I've this error :
A fetch request must be a simple member access expression of the kind o => o.Related; 'pan.Adn.Fabricant' is too complex.
Nom du paramètre : relatedObjectSelector
My Pan object reference a Adn object.
<many-to-one name="AdnMonture" column="IDADN_Mont" cascade="save-update" not-null="true" />
This Adn object reference all the data I presented before. (cf. the hbm.xml before)
Is there any other solution for this case ?
Maybe with join ?
Edit 2
I tryed to use ThenFetch
return (from pan in session.Query<PanierMonture>()
.Fetch(pan => pan.AdnMonture)
.ThenFetch(adn => adn.Fabricant)
.ThenFetch(adn => adn.Reference)
.ThenFetch(adn => adn.Marque)
orderby pan.AdnMonture.Marque.Nom
select pan).ToList<PanierMonture>();
the first ThenFirst works
But the second is blocked by intellisence.
I use the Fabricant object.
So I tryied that :
return (from pan in session.Query<PanierMonture>()
.Fetch(pan => pan.AdnMonture)
.ThenFetch(adn => adn.Fabricant)
.Then(adn => adn.Reference)
.Then(adn => adn.Marque)
orderby pan.AdnMonture.Marque.Nom
select pan).ToList<PanierMonture>();
But again it doesn't work. intellisense don't give me the adn object
I found this workaround :
return (from pan in session.Query<PanierMonture>()
.Fetch(pan => pan.AdnMonture)
.ThenFetch(adn => adn.Fabricant)
.Fetch(pan => pan.AdnMonture)
.ThenFetch(adn => adn.Marque)
.Fetch(pan => pan.AdnMonture)
.ThenFetch(adn => adn.Reference)
.Fetch(pan => pan.AdnMonture)
.ThenFetch(adn => adn.Coloris)
.Fetch(pan => pan.AdnMonture)
.ThenFetch(adn => adn.TailleMonture)
orderby pan.AdnMonture.Marque.Nom
select pan).ToList<PanierMonture>();
Is it correct ?
The generated sql query is a bit strange :
select ..... from Panier_Monture paniermont0_ left outer join ADN_Monture adnmonture1_ on paniermont0_.IDADN_Mont=adnmonture1_.IDADN_Monture left outer join Fabricant fabricant2_ on adnmonture1_.IDFabricant=fabricant2_.IDFabricant left outer join ADN_Monture adnmonture3_ on paniermont0_.IDADN_Mont=adnmonture3_.IDADN_Monture left outer join Marque marque4_ on adnmonture3_.IDMarque=marque4_.IDMarque left outer join ADN_Monture adnmonture5_ on paniermont0_.IDADN_Mont=adnmonture5_.IDADN_Monture left outer join Reference reference6_ on adnmonture5_.IDReference=reference6_.IDReference left outer join ADN_Monture adnmonture7_ on paniermont0_.IDADN_Mont=adnmonture7_.IDADN_Monture left outer join Coloris coloris8_ on adnmonture7_.IDColoris=coloris8_.IDColoris left outer join ADN_Monture adnmonture9_ on paniermont0_.IDADN_Mont=adnmonture9_.IDADN_Monture left outer join Taille_Monture taillemont10_ on adnmonture9_.IDTaille=taillemont10_.IDTaille left outer join ADN_Monture adnmonture11_ on paniermont0_.IDADN_Mont=adnmonture11_.IDADN_Monture left outer join Marque marque12_ on adnmonture11_.IDMarque=marque12_.IDMarque order by marque12_.Nom asc
The table AdnMonture is repeated each times ?
Is there a chance of problem ?
Regards and again thank you
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
请参阅此答案:在 NHibernate 3 中使用 Linq 时进行急切加载
现在您的链接实体将被获取,并且您不会遇到 SELECT N+1 问题
See this answer : Eager load while using Linq in NHibernate 3
Now your linked entities will be fetched and you won't have SELECT N+1 problems