[NHibernate/C#] Vuurt veel queries af, waarom?

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Guillome
  • Registratie: Januari 2001
  • Niet online
Hallo,

Probleem is simpel: NHibernate vuurt heel veel queries (te zien in sql profiler) af als ik een query doe. Een simpele testcase hieronder.
Per product voert hij een query uit om de categorie erbij te zoeken. Waarom niet een join met alle data in 1 keer?
lazy op false of fetch op join/select maakt geen verschil.

Mijn mapping is:

Product
code:
1
2
3
4
5
6
7
8
  <class name="Product">
    <id name="Id">
      <generator class="identity" />
    </id>
    <property name="Name"/>
    <property name="Discontinued" />
    <many-to-one class="Category" name="Category" column="CategoryId" cascade="all" fetch="select" lazy="proxy"></many-to-one>
  </class>


Categorie:
code:
1
2
3
4
5
6
  <class name="Category">
    <id name="Id">
      <generator class="identity" />
    </id>
    <property name="Name"></property>
  </class>


De classes:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
  public class Product
  {
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual Category Category { get; set; }
    public virtual bool Discontinued { get; set; }
  }
  public class Category
  {
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
  }


En de C# code:
C#:
1
2
3
4
5
6
var products = session.Query<Product>();

foreach (var _product in products)
      {
        Console.WriteLine("{0} - {1} {2}", _product.Id, _product.Name, _product.Category.Name);
      }


En voor wie het nodig heeft de (eerste aantal) afgevuurde queries:
SQL:
1
2
3
4
5
6
7
exec sp_executesql N'select product0_.Id as Id1_, product0_.Name as Name1_, product0_.Discontinued as Disconti3_1_, product0_.CategoryId as CategoryId1_ from Product product0_ where charindex(@p0, product0_.Name, 0)=@p1',N'@p0 nvarchar(4000),@p1 int',@p0=N'Test',@p1=1

exec sp_executesql N'SELECT category0_.Id as Id0_0_, category0_.Name as Name0_0_ FROM Category category0_ WHERE category0_.Id=@p0',N'@p0 int',@p0=1

exec sp_executesql N'SELECT category0_.Id as Id0_0_, category0_.Name as Name0_0_ FROM Category category0_ WHERE category0_.Id=@p0',N'@p0 int',@p0=2

etc..


Kan dit ook anders? We werken namelijk met grote databases en dito aantal gebruikers

If then else matters! - I5 12600KF, Asus Tuf GT501, Asus Tuf OC 3080, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


Acties:
  • 0 Henk 'm!

  • Daspeed
  • Registratie: Maart 2001
  • Laatst online: 09:11
http://nhforge.org/doc/nh/en/index.html

Je kunt NHibernate behoorlijk sturen. Je kunt bijvoorbeeld eager fetchen, waardoor category wordt ge-left-joined, maar je kunt ook per batch laten ophalen.

Acties:
  • 0 Henk 'm!

  • matthijsln
  • Registratie: Augustus 2002
  • Laatst online: 13:14
Guillome schreef op donderdag 24 mei 2012 @ 16:56:
Probleem is simpel: NHibernate vuurt heel veel queries (te zien in sql profiler) af als ik een query doe. Een simpele testcase hieronder.
Ho ho, NHibernate voert dat alleen uit omdat je per product _product.Category.Name opvraagt.
Per product voert hij een query uit om de categorie erbij te zoeken. Waarom niet een join met alle data in 1 keer?
lazy op false of fetch op join/select maakt geen verschil.
Lazy op false zou wel moeten leiden tot het direct laden van de categorieen, weet je het zeker? Nou is het niet verstandig om alles maar op lazy=false te zetten. Voor je het weet laad je namelijk de hele database in.

Er zit nog steeds een database onder NHibernate. Dit betekent dat je altijd na zult moeten denken over welk onderdeel je wilt laden op een zo'n efficient mogelijke manier. Het probleem dat jij hebt heet het N+1 select probleem (je haalt in 1 query de producten op, maar voor elk product (N) wordt weer een query gedaan). Via die link kom je bij uitleg en oplossingen. Gebruik bijvoorbeeld een query met "left join fetch".