2015-04-22 2 views
1

Я обновляю проект, написанный на C#/wpf, и использует nhibernate и sql-сервер. Когда я протестировал программу, я заметил, что она очень медленная при получении определенного списка из базы данных.Nhibernate/linq query чрезвычайно медленный

Ниже приведен код доступа к данным сниппет:

public static List<Ticket> GetListFromPeriod(DateTime beginDatum, DateTime eindDatum) 
    { 
     List<Ticket> list = new List<Ticket>(); 
     using (var session = NhibernateHelper.OpenSession()) 
     { 
      using (var transaction = session.BeginTransaction()) 
      { 
       list = session.Query<Ticket>() 
        .Where(x => x.Tijdstip.Date <= eindDatum && x.Tijdstip.Date >= beginDatum).ToList(); 
      } 
     } 
     foreach (var item in list) 
     { 
      item.IsSaved = true; 
     } 
     return list; 
    } 

Этот маленький кусочек кода нарушителем и занимает около секунд, чтобы получить 558 объектов:

list = session.Query<Ticket>() 
.Where(x => x.Tijdstip.Date <= eindDatum && x.Tijdstip.Date >= beginDatum).ToList(); 

дополнительная информация:

  • Ticke т имеет 1 ко многим отношений с TicketRecord
  • Klant (= Клиент на английском языке) имеет 1-ко-многим с Ticket
  • PapierSoort (= категория бумаги на английском языке) имеет 1 для многих отношения с TicketRecord

Отображения:

public TicketMap() 
    { 
     Table("tblTicket"); 
     Id(x => x.Id) 
      .Column("TicketId") 
      .UnsavedValue(0) 
      .Not.Nullable(); 
     Map(x => x.Tijdstip) 
      .Column("Tickettijdstip") 
      .Not.Nullable(); 
     References(x => x.Klant) 
      .Column("KlantId") 
      .Not.Nullable(); 
     HasMany(x => x.TicketRecordsAsList) 
      .Table("tblTicketRecord") 
      .Inverse() 
      .KeyColumn("ticketid").Cascade.All();    
    } 


public TicketRecordMap() 
    { 
     Table("tblTicketrecord"); 
     Id(x => x.Id) 
      .Column("ticketrecordid") 
      .Not.Nullable(); 
     Map(x => x.Prijs) 
      .Column("ticketrecordprijs") 
      .Not.Nullable(); 
     Map(x => x.Gewicht) 
      .Column("ticketrecordgewicht"); 
     References(x => x.Soort) 
      .Column("soortid") 
      .Not.Nullable(); 
    } 

public KlantMap() 
    { 
     Table("tblKlant"); 
     Id(x => x.Id) 
      .Column("klantid") 
      .Not.Nullable(); 
     Map(x => x.Naam) 
      .Column("klantnaam"); 
     Map(x => x.RijksregisterNr) 
      .Column("klantrijksregisternr"); 
     Map(x => x.Idnr) 
      .Column("klantidnr"); 
     Map(x => x.Adres) 
      .Column("klantadres"); 
     Map(x => x.Actief) 
      .Column("actief") 
      .Not.Nullable(); 
    } 

public PapierSoortMap() 
    { 
     Table("tblSoort"); 
     Id(x => x.Id) 
      .Column("papiersoortid") 
      .Not.Nullable(); 
     Map(x => x.Naam) 
      .Column("papiersoortnaam") 
      .Not.Nullable(); 
     Map(x => x.Prijs) 
      .Column("papiersoortprijs"); 
     Map(x => x.IsDefault) 
      .Column("papierisdefault") 
      .Not.Nullable(); 
    } 

Nhibernate помощник:

public static class NhibernateHelper 
{ 
    private static ISessionFactory _sessionFactory; 

    private static ISessionFactory SessionFactory 
    { 
     get 
     { 
      if (_sessionFactory == null) 
       InitializeSessionFactory(); 

      return _sessionFactory; 
     } 
    } 

    private static void InitializeSessionFactory() 
    { 
     _sessionFactory = Fluently.Configure() 
      .Database(MsSqlConfiguration.MsSql2008 
      .ConnectionString(x => x.FromConnectionStringWithKey("DBconnect")) 
          //.ConnectionString(
          // @"Data Source=.\SQLEXPRESS;AttachDbFilename=C:\Solutions\KassaOPM\KassaOPM.UI\DB.mdf;Integrated Security=True;User Instance=True") 
          .ShowSql()) 

      .Mappings(m => 
         m.FluentMappings 
          .AddFromAssemblyOf<KlantMap>() 
          .Conventions.Add(FluentNHibernate.Conventions.Helpers.DefaultLazy.Never())) 
      .BuildSessionFactory(); 
    } 

    public static ISession OpenSession() 
    { 
     return SessionFactory.OpenSession(); 
    } 

} 

В SQL Server Profiler я нашел 3 другой запрос о том, что в настоящее время та или иная строчка:

Первый (происходит только в начале):

exec sp_executesql N' 
select ticket0_.TicketId as TicketId3_, ticket0_.Tickettijdstip as Ticketti2_3_, ticket0_.KlantId as KlantId3_ 
from tblTicket ticket0_ 
where dateadd(dd, 0, datediff(dd, 0, ticket0_.Tickettijdstip))<[email protected] and dateadd(dd, 0, datediff(dd, 0, ticket0_.Tickettijdstip))>[email protected]',N'@p0 datetime,@p1 datetime',@p0='2015-04-22 00:00:00',@p1='2015-03-22 00:00:00' 

второй и третий:

exec sp_executesql N' 
SELECT klant0_.klantid as klantid0_0_, klant0_.klantnaam as klantnaam0_0_, klant0_.klantrijksregisternr as klantrij3_0_0_, klant0_.klantidnr as klantidnr0_0_, klant0_.klantadres as klantadres0_0_, klant0_.actief as actief0_0_ 
FROM tblKlant klant0_ 
WHERE [email protected]',N'@p0 int',@p0=4235 

exec sp_executesql N' 
SELECT ticketreco0_.ticketid as ticketid2_, ticketreco0_.ticketrecordid as ticketre1_2_, ticketreco0_.ticketrecordid as ticketre1_4_1_, ticketreco0_.ticketrecordprijs as ticketre2_4_1_, ticketreco0_.ticketrecordgewicht as ticketre3_4_1_, ticketreco0_.soortid as soortid4_1_, papiersoor1_.papiersoortid as papierso1_1_0_, papiersoor1_.papiersoortnaam as papierso2_1_0_, papiersoor1_.papiersoortprijs as papierso3_1_0_, papiersoor1_.papierisdefault as papieris4_1_0_ 
FROM tblTicketrecord ticketreco0_ inner join tblSoort papiersoor1_ on ticketreco0_.soortid=papiersoor1_.papiersoortid 
WHERE [email protected]',N'@p0 int',@p0=27342 

Я подозреваю, что с кодом что-то не так, но я не могу понять, в чем проблема.

Если вам нужна любая другая информация, пожалуйста, спросите, и я сделаю все возможное, чтобы дать вам то, что вам нужно.

Заранее спасибо

ответ

0

Все один-ко многим отображений, связанных с билетами, удовлетворяющих условию даты, кажется, быть извлечена в бизнес-объекта, в соответствии со вторым и третьим запросам.

Возможно, вам следует объявить свое отношение ко многим отношениям ленивым, чтобы избежать дополнительной (и, возможно, ненужной) загрузки.

+0

Спасибо за ваш быстрый ответ, я сделал то, что вы предложили, и сопоставил одно со многими отношениями как «ленивые», но, к сожалению, это не имело никакого эффекта. – JensVT

+0

Вы удалили стандартное соглашение по умолчанию из своей конфигурации в функции InitializeSessionFactory? Не уверен, если это связано. – tumasgiu

+0

Ну, так как я думаю, что вы правы, что стандартная ленивая конвенция - это проблема, которую я пытаюсь исправить.Для того, чтобы Nhibernate работал, каждый метод и свойство в моих классах из бизнес-уровня должны быть ** виртуальными **. Так как в этом проекте используется Caliburn.Micro (MVVM), методы propertychanged находятся в dll Caliburn.Micro, поэтому я не могу сделать их виртуальными. Если я смогу исправить эту проблему, я опубликую свое решение здесь для других людей. Но пока я буду отмечать ваш ответ как решение, так как вы указали мне в правильном направлении, спасибо за вашу помощь! – JensVT

Смежные вопросы