1

我正在使用Nhibernate 3.2打印SqlServer數據庫的c#,並試圖使用multiquery和Futures來加載子集合。ToFuture的延遲加載子集合

反正我可以得到它使用LINQ to NHibernate的工作,但查看SQL時發送給它看起來好像它加載除了孩子所有的父對象爲子集取的對象(數據庫喜歡它是渴望加載)。我很好奇,如果有可能改變這種行爲,只拉動所需的子對象列。

下面是演示此問題的代碼示例。

public class Parent : Entity 
    { 
     public virtual string Name { get; set; } 
     public virtual IList<Child> Children { get; set; } 
    } 


public class Child : Entity 
    { 
     public virtual int Age { get; set; } 
     public virtual string Name { get; set; } 
     public virtual Parent Parent { get; set; } 
    } 


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"); 
     } 
    } 


public class ParentClassMap : ClassMap<Parent> 
    { 
     public ParentClassMap() 
     { 
     Id(x => x.Id, "Id"); 
     Map(x => x.Name); 
     this.HasMany(x => x.Children).KeyColumn("ParentId"); 
     } 
    } 



    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(); 
     } 
     } 
    } 

測試用例

[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); 

     } 
    } 

SQL:

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 

從SQL事件探查器的輸出是:

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 [email protected]; 
    select parent0_.Id as Id3_, parent0_.Name as Name3_ from [Parent] parent0_ where [email protected]; 
',N'@p0 bigint,@p1 bigint',@p0=1,@p1=1 

有沒有人有什麼建議?

感謝您的時間

回答

1

只是縮短了代碼

public Parent GetParentWithChildrenInitialised(int id) 
{ 
    using (var session = SessionFactory.OpenSession()) 
    { 
     return session.Query<Parent>() 
      .Where(p => p.Id == id) 
      .FetchMany(x => x.Children) 
      .SingleOrDefault(); 
    } 
} 

我本人來說會擺脫資源庫的,因爲它增加了不必要的抽象,使得難以調整性能,的ISession已經像程序存儲庫。

更好的選擇是使用session.Get(parentId);,因爲如果需要孩子,它會使用lvl1 /會話緩存或上面的查詢。

還使用sessionfactory創建會話,因爲它是線程安全的,會話不是。