Я обновляю проект, написанный на 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
Я подозреваю, что с кодом что-то не так, но я не могу понять, в чем проблема.
Если вам нужна любая другая информация, пожалуйста, спросите, и я сделаю все возможное, чтобы дать вам то, что вам нужно.
Заранее спасибо
Спасибо за ваш быстрый ответ, я сделал то, что вы предложили, и сопоставил одно со многими отношениями как «ленивые», но, к сожалению, это не имело никакого эффекта. – JensVT
Вы удалили стандартное соглашение по умолчанию из своей конфигурации в функции InitializeSessionFactory? Не уверен, если это связано. – tumasgiu
Ну, так как я думаю, что вы правы, что стандартная ленивая конвенция - это проблема, которую я пытаюсь исправить.Для того, чтобы Nhibernate работал, каждый метод и свойство в моих классах из бизнес-уровня должны быть ** виртуальными **. Так как в этом проекте используется Caliburn.Micro (MVVM), методы propertychanged находятся в dll Caliburn.Micro, поэтому я не могу сделать их виртуальными. Если я смогу исправить эту проблему, я опубликую свое решение здесь для других людей. Но пока я буду отмечать ваш ответ как решение, так как вы указали мне в правильном направлении, спасибо за вашу помощь! – JensVT