Nhibernate/linq 查询速度极慢
Nhibernate/linq query is extremely slow
我正在更新一个用 c#/wpf 编写的项目,它使用了 nhibernate 和 sql 服务器。当我测试该程序时,我注意到它在从数据库中检索特定列表时非常慢。
下面是数据访问代码片段:
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;
}
这段代码很麻烦,需要 90 秒来检索 558 个对象:
list = session.Query<Ticket>()
.Where(x => x.Tijdstip.Date <= eindDatum && x.Tijdstip.Date >= beginDatum).ToList();
一些附加信息:
- Ticket 与 TicketRecord
具有一对多关系
- Klant(= 英语中的客户)与 Ticket
具有一对多关系
- PapierSoort(=英文的paper category)与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))<=@p0 and dateadd(dd, 0, datediff(dd, 0, ticket0_.Tickettijdstip))>=@p1',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 klant0_.klantid=@p0',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 ticketreco0_.ticketid=@p0',N'@p0 int',@p0=27342
我怀疑代码有问题,但我似乎无法弄清楚问题出在哪里。
如果您需要任何其他信息,请询问,我会尽我所能为您提供所需的信息。
提前致谢
根据第二个和第三个查询,与满足日期条件的票相关的所有一对多映射似乎都在您的业务对象中获取。
也许您应该将一对多关系声明为惰性关系,以避免额外的(可能是不必要的)加载。
我正在更新一个用 c#/wpf 编写的项目,它使用了 nhibernate 和 sql 服务器。当我测试该程序时,我注意到它在从数据库中检索特定列表时非常慢。
下面是数据访问代码片段:
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;
}
这段代码很麻烦,需要 90 秒来检索 558 个对象:
list = session.Query<Ticket>()
.Where(x => x.Tijdstip.Date <= eindDatum && x.Tijdstip.Date >= beginDatum).ToList();
一些附加信息:
- Ticket 与 TicketRecord 具有一对多关系
- Klant(= 英语中的客户)与 Ticket 具有一对多关系
- PapierSoort(=英文的paper category)与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))<=@p0 and dateadd(dd, 0, datediff(dd, 0, ticket0_.Tickettijdstip))>=@p1',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 klant0_.klantid=@p0',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 ticketreco0_.ticketid=@p0',N'@p0 int',@p0=27342
我怀疑代码有问题,但我似乎无法弄清楚问题出在哪里。
如果您需要任何其他信息,请询问,我会尽我所能为您提供所需的信息。
提前致谢
根据第二个和第三个查询,与满足日期条件的票相关的所有一对多映射似乎都在您的业务对象中获取。
也许您应该将一对多关系声明为惰性关系,以避免额外的(可能是不必要的)加载。