Hey All,
I'm currently using c# with Nhibernate 3.2 hitting a SqlServer database, and I am trying to work with multiquery's and Futures to load a child collection.
Anyways I can get it to work using Linq to Nhibernate, but when viewing the sql is sent to the database it looks as if it is loading all of the parent objects in addition to the child objects for the child collection fetch (Like it is eager loading). I was curious if it was possible to change this behavior to only pull the needed child object columns.
Here is an example of code that illustrates this issue.
Code:
public class Parent : Entity
{
public virtual string Name { get; set; }
public virtual IList<Child> Children { get; set; }
}
Code:
public class Child : Entity
{
public virtual int Age { get; set; }
public virtual string Name { get; set; }
public virtual Parent Parent { get; set; }
}
Code:
public class ChildClassMap : ClassMap<Child>
{
public ChildClassMap()
{
Id(x => x.Id,"Id");
Map(x => x.Age);
Map(x => x.Name);
this.References(x => x.Parent).Column("ParentId").ForeignKey("Id");
}
}
Code:
public class ParentClassMap : ClassMap<Parent>
{
public ParentClassMap()
{
Id(x => x.Id, "Id");
Map(x => x.Name);
this.HasMany(x => x.Children).KeyColumn("ParentId");
}
}
Code:
public class FamilyRepository : NHibernateRepository<Parent>
{
public Parent GetParent(int id)
{
using (var session = this.Session.OpenSession())
{
var parent = session.Query<Parent>()
.Where(p => p.Id == id);
parent.FetchMany(x => x.Children)
.ToFuture();
return parent.ToFuture().SingleOrDefault();
}
}
}
Code:
[TestClass]
public class FamilyTests
{
[TestMethod]
public void Should_Get_Parent_And_Children()
{
// arrange
var repo = new FamilyRepository();
// act
var parent = repo.GetParent(1);
// assert
Assert.AreNotEqual(null, parent);
Assert.AreEqual("TheOldOne", parent.Name);
Assert.AreEqual(3, parent.Children.Count);
Assert.AreEqual(4, parent.Children[1].Age);
Assert.AreEqual("TheMiddleOne", parent.Children[1].Name);
}
}
Code:
CREATE TABLE [dbo].[Parent](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](50) NOT NULL,
CONSTRAINT [PK_Parent] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Child](
[Id] [int] IDENTITY(1,1) NOT NULL,
[ParentId] [int] NOT NULL,
[Age] [int] NOT NULL,
[Name] [varchar](50) NOT NULL,
CONSTRAINT [PK_Child] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[Child] WITH CHECK ADD CONSTRAINT [FK_Child_Parent] FOREIGN KEY([ParentId])
REFERENCES [dbo].[Parent] ([Id])
GO
ALTER TABLE [dbo].[Child] CHECK CONSTRAINT [FK_Child_Parent]
GO
Set Identity_Insert [dbo].[Parent] on
insert into [dbo].[Parent]
(Id, Name)
values (1, 'TheOldOne');
insert into [dbo].[Parent]
(Id, Name)
values (2, 'TheOtherOne');
Set Identity_Insert [dbo].[Parent] off
GO
Set Identity_Insert [dbo].[Child] on
insert into [dbo].[Child]
(Id, ParentId, Age, Name)
values(1,1,3,'TheYoungOne')
insert into [dbo].[Child]
(Id, ParentId, Age, Name)
values(2,1,4,'TheMiddleOne')
insert into [dbo].[Child]
(Id, ParentId, Age, Name)
values(3,1,7,'TheFirstOne')
Set Identity_Insert [dbo].[Child] off
The output from the sql profiler is:
Code:
exec sp_executesql N'select parent0_.Id as Id3_0_, children1_.Id as Id2_1_, parent0_.Name as Name3_0_, children1_.Age as Age2_1_, children1_.Name as Name2_1_, children1_.ParentId as ParentId2_1_, children1_.ParentId as ParentId0__, children1_.Id as Id0__ from [Parent] parent0_ left outer join [Child] children1_ on parent0_.Id=children1_.ParentId where parent0_.Id=@p0;
select parent0_.Id as Id3_, parent0_.Name as Name3_ from [Parent] parent0_ where parent0_.Id=@p1;
',N'@p0 bigint,@p1 bigint',@p0=1,@p1=1
Does anyone have any suggestions?
thanks for your time
PS: I was going to post this on the Nhibernate forum but it was locked