1

현재 Nhibernate 3.2에서 SqlServer 데이터베이스를 사용하면서 C#을 사용하고 있으며 하위 컬렉션을로드하기 위해 multiquery 및 Futures에서 작업하려고합니다.ToFuture로 지연 하위 컬렉션로드

어쨌든 나는 Linq를 사용하여 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

그냥 내가 personaly 저장소를 제거 할

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/session 캐시 또는 하위가 필요할 경우 위의 쿼리를 사용하기 때문입니다.

스레드가 안전하고 세션이 없으므로 sessionfactory를 사용하여 세션을 만드십시오.