为什么 NHibernate 在更新 child 期间不在 one-to-many 中发送额外的 select 查询?
Why NHibernate is not sending extra select query in one-to-many during updating child?
我对 NHibernate 很陌生,我制作了简单的应用程序来测试 NHibernate 和 Entity Framework 性能。我注意到更新 one-to-many 关系中的 child 存在一些问题。在更新期间 child Entity Framework 正在发送额外的 select 查询以获取 children。由于延迟加载,这似乎没问题。但是 NHibernate 不会发送额外的 select 查询来获取 children 即使启用了延迟加载。我的问题来了。为什么它不发送额外的 select 查询?为什么不需要它?
感谢您的帮助。
用于更新的 NHibernate 代码:
var students = nHibernateSQLServerSession.Query<Student>().Where(s => s.Grades.Count > 0).Take(records).ToList();
using (nHibernateSQLServerSession.BeginTransaction())
{
foreach (var student in students)
{
student.Grades.ElementAt(rand.Next(student.Grades.Count)).Score = rand.Next(7);
}
nHibernateSQLServerSession.GetCurrentTransaction().Commit();
}
Entity Framework更新代码:
using (var db = new ORMTesterContext("name=ORMTesterSQLServer"))
{
students = db.Students.Where(s => s.Grades.Count > 0).Take(records).ToList();
foreach (var student in students)
{
student.Grades.ElementAt(rand.Next(student.Grades.Count)).Score = rand.Next(7);
}
db.SaveChanges();
}
NHibernate 中的关系映射:
学生
<set name="Grades" inverse="true">
<key column="StudentId" />
<one-to-many class="NHibernate.DataAccess.Entities.Grades.Grade, NHibernate.DataAccess" />
</set>
成绩
<many-to-one name="Student" class="NHibernate.DataAccess.Entities.Students.Student, NHibernate.DataAccess" column="StudentId" cascade="delete" />
执行的查询:
NHibernate:
exec sp_executesql
N'select TOP (@p0) student0_.Id as id1_4_, student0_.Name as name2_4_, student0_.Surname as surname3_4_
from Students student0_
where (select (count(*))
from Grades grades1_
where student0_.Id=grades1_.StudentId)>@p1',N'@p0 int,@p1 int',@p0=1,@p1=0
exec sp_executesql
N'UPDATE Grades
SET Score = @p0, StudentId = @p1, TeacherId = @p2
WHERE Id = @p3',N'@p0 int,@p1 int,@p2 int,@p3 int',@p0=1,@p1=78761,@p2=601,@p3=1202
Entity Framework:
SELECT TOP (1)
[Project1].[Id] AS [Id],
[Project1].[Name] AS [Name],
[Project1].[Surname] AS [Surname]
FROM ( SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name],
[Extent1].[Surname] AS [Surname],
(SELECT
COUNT(1) AS [A1]
FROM [dbo].[Grades] AS [Extent2]
WHERE [Extent1].[Id] = [Extent2].[StudentId]) AS [C1]
FROM [dbo].[Students] AS [Extent1]
) AS [Project1]
WHERE [Project1].[C1] > 0
exec sp_executesql N'SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Score] AS [Score],
[Extent1].[StudentId] AS [StudentId],
[Extent1].[TeacherId] AS [TeacherId]
FROM [dbo].[Grades] AS [Extent1]
WHERE [Extent1].[StudentId] = @EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=78761
exec sp_executesql N'UPDATE [dbo].[Grades]
SET [Score] = @0
WHERE ([Id] = @1)
',N'@0 int,@1 int',@0=6,@1=1201
好吧,我错了。我完全忘记了 NHibernate 缓存。成绩已经缓存在第一次查询中,并且正在检查下一次尝试的查询,这就是为什么我在第一次尝试时没有注意到额外的查询。
我对 NHibernate 很陌生,我制作了简单的应用程序来测试 NHibernate 和 Entity Framework 性能。我注意到更新 one-to-many 关系中的 child 存在一些问题。在更新期间 child Entity Framework 正在发送额外的 select 查询以获取 children。由于延迟加载,这似乎没问题。但是 NHibernate 不会发送额外的 select 查询来获取 children 即使启用了延迟加载。我的问题来了。为什么它不发送额外的 select 查询?为什么不需要它? 感谢您的帮助。
用于更新的 NHibernate 代码:
var students = nHibernateSQLServerSession.Query<Student>().Where(s => s.Grades.Count > 0).Take(records).ToList();
using (nHibernateSQLServerSession.BeginTransaction())
{
foreach (var student in students)
{
student.Grades.ElementAt(rand.Next(student.Grades.Count)).Score = rand.Next(7);
}
nHibernateSQLServerSession.GetCurrentTransaction().Commit();
}
Entity Framework更新代码:
using (var db = new ORMTesterContext("name=ORMTesterSQLServer"))
{
students = db.Students.Where(s => s.Grades.Count > 0).Take(records).ToList();
foreach (var student in students)
{
student.Grades.ElementAt(rand.Next(student.Grades.Count)).Score = rand.Next(7);
}
db.SaveChanges();
}
NHibernate 中的关系映射:
学生
<set name="Grades" inverse="true">
<key column="StudentId" />
<one-to-many class="NHibernate.DataAccess.Entities.Grades.Grade, NHibernate.DataAccess" />
</set>
成绩
<many-to-one name="Student" class="NHibernate.DataAccess.Entities.Students.Student, NHibernate.DataAccess" column="StudentId" cascade="delete" />
执行的查询:
NHibernate:
exec sp_executesql
N'select TOP (@p0) student0_.Id as id1_4_, student0_.Name as name2_4_, student0_.Surname as surname3_4_
from Students student0_
where (select (count(*))
from Grades grades1_
where student0_.Id=grades1_.StudentId)>@p1',N'@p0 int,@p1 int',@p0=1,@p1=0
exec sp_executesql
N'UPDATE Grades
SET Score = @p0, StudentId = @p1, TeacherId = @p2
WHERE Id = @p3',N'@p0 int,@p1 int,@p2 int,@p3 int',@p0=1,@p1=78761,@p2=601,@p3=1202
Entity Framework:
SELECT TOP (1)
[Project1].[Id] AS [Id],
[Project1].[Name] AS [Name],
[Project1].[Surname] AS [Surname]
FROM ( SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name],
[Extent1].[Surname] AS [Surname],
(SELECT
COUNT(1) AS [A1]
FROM [dbo].[Grades] AS [Extent2]
WHERE [Extent1].[Id] = [Extent2].[StudentId]) AS [C1]
FROM [dbo].[Students] AS [Extent1]
) AS [Project1]
WHERE [Project1].[C1] > 0
exec sp_executesql N'SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Score] AS [Score],
[Extent1].[StudentId] AS [StudentId],
[Extent1].[TeacherId] AS [TeacherId]
FROM [dbo].[Grades] AS [Extent1]
WHERE [Extent1].[StudentId] = @EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=78761
exec sp_executesql N'UPDATE [dbo].[Grades]
SET [Score] = @0
WHERE ([Id] = @1)
',N'@0 int,@1 int',@0=6,@1=1201
好吧,我错了。我完全忘记了 NHibernate 缓存。成绩已经缓存在第一次查询中,并且正在检查下一次尝试的查询,这就是为什么我在第一次尝试时没有注意到额外的查询。