1

사용되는 컨텍스트에 따라 다른 그래프 (관련 엔터티)를 사용하여 개체를로드하는 가장 좋은 방법을 파악하려고합니다. 내가 이해하기 위해 노력하고있어다른 그래프를 사용하여 개체를로드하는 올바른 패턴 찾기

public class Puzzle 
{ 
    public Id{ get; private set; } 
    public string TopicUrl { get; set; } 
    public string EndTopic { get; set; } 
    public IEnumerable<Solution> Solutions { get; set; } 
    public IEnumerable<Vote> Votes { get; set; } 
    public int SolutionCount { get; set; } 
    public User User { get; set; } 
} 
public class Solution 
{ 
    public int Id { get; private set; } 
    public IEnumerable<Step> Steps { get; set; } 
    public int UserId { get; set; } 
} 
public class Step 
{ 
    public Id { get; set; } 
    public string Url { get; set; } 
} 
public class Vote 
{ 
    public id Id { get; set; } 
    public int UserId { get; set; } 
    public int VoteType { get; set; } 
} 

내가 그것을 사용하고 방법에 따라 다르게이 정보를로드하는 방법입니다 : 예를 들어

여기에 내 도메인 개체의 샘플입니다.

예를 들어, 첫 페이지에는 모든 퍼즐 목록이 있습니다. 이 시점에서 나는 수수께끼를위한 해결책이나 그 해결책의 단계에 신경을 쓰지 않는다. 내가 원하는 건 퍼즐 뿐이야. 나는이 같은 내 컨트롤러에서 그들을로드합니다 :

public ActionResult Index(/* parameters */) 
{ 
    ... 
    var puzzles = _puzzleService.GetPuzzles(); 
    return View(puzzles); 
} 

을 나중에 현재 사용자 만이 솔루션에 대해 내가 지금 관심 퍼즐보기를. 모든 솔루션과 모든 단계를 전체 그래프로로드하고 싶지는 않습니다. 내 IPuzzleService 내부

public ActionResult Display(int puzzleId) 
{ 
    var puzzle = _accountService.GetPuzzleById(puzzleId); 
    //I want to be able to access my solutions, steps, and votes. just for the current user. 
} 

, 내 방법은 다음과 같이 :

public IEnumerable<Puzzle> GetPuzzles() 
{ 
    using(_repository.OpenSession()) 
    { 
     _repository.All<Puzzle>().ToList(); 
    } 
} 
public Puzzle GetPuzzleById(int puzzleId) 
{ 
    using(_repository.OpenSession()) 
    { 
     _repository.All<Puzzle>().Where(x => x.Id == puzzleId).SingleOrDefault(); 
    } 
} 

게으른 로딩이 정말 현실 세계에서 작동하지 않습니다, 내 세션이 바로 작업의 각 단위 후 배치되고 있기 때문이다. 내 컨트롤러에는 저장소에 대한 개념이 없으므로 세션 상태를 관리하지 않으며 뷰가 렌더링 될 때까지 세션 상태를 유지할 수 없습니다.

나는 여기에 사용할 올바른 패턴이 무엇인지 알아 내려고하고 있습니다. 내 서비스에 GetPuzzleWithSolutionsAndVotes 이상의 다양한 오버로드가 있습니까 (예 : GetPuzzlesForDisplayViewGetPuzzlesForListView)?

나는 의미가 있습니까? 나는 기지에서 벗어나나요? 도와주세요.

답변

2

나는 Lazy 로딩을 사용할 수없는 비슷한 경우가있었습니다.

하나 또는 두 개의 사례 만 필요하면 제안 할 때 가장 쉬운 방법은 별도의 GetPuzleWithXYZ() 메소드를 생성하는 것입니다.

유창한 인터페이스로 작은 쿼리 개체를 만들 수도 있습니다.

뭔가 같은 ...

public interface IPuzzleQuery 
{ 
    IPuzzleLoadWith IdEquals(int id); 
} 

public interface IPuzzleLoadWith 
{ 
    ISolutionLoadWith WithSolutions(); 

    IPuzzleLoadWith WithVotes(); 
} 

public interface ISolutionLoadWith 
{ 
    IPuzzleLoadWith AndSteps(); 
} 

public class PuzzleQueryExpressionBuilder : IPuzzleQuery, IPuzzleLoadWith, ISolutionLoadWith 
{ 
    public int Id { get; private set; } 
    public bool LoadSolutions { get; private set; } 
    public bool LoadVotes { get; private set; } 
    public bool LoadSteps { get; private set; } 

    public IPuzzleLoadWith IdEquals(int id) 
    { 
     Id = id; 
     return this;  
    } 

    public ISolutionLoadWith WithSolutions() 
    { 
     LoadSolutions = true; 
     return this; 
    } 

    public IPuzzleLoadWith WithVotes() 
    { 
     LoadVotes = true; 
     return this; 
    } 

    public IPuzzleLoadWith AndSteps() 
    { 
     LoadSteps = true; 
     return this; 
    } 
} 

는 다음 저장소를 가져 오기() 메소드는 식 작성기를 인스턴스화하고 호출자에게 같을 것이다

public Puzzle Get(Action<IPuzzleQuery> expression) 
{ 
    var criteria = new PuzzleQueryExpressionBuilder(); 

    expression(criteria); 

    var query = _repository.All<Puzzle>().Where(x => x.Id == criteria.Id) 

    if(criteria.LoadSolutions) .... 

    if(criteria.LoadSteps) .... 

    if(criteria.LoadVotes) .... 

    ... 
    ... 

    return query.FirstOrDefault(); 
} 

및 일반 전화를 전달할 수 ...

Puzzle myPuzzle = Repository.Get(where => where.IdEquals(101).WithSolutions()); 

Puzzle myPuzzle = Repository.Get(where => where.IdEquals(101).WithSolutions().AndSteps()); 

Puzzle myPuzzle = Repository.Get(where => where.IdEquals(101).WithVotes().WithSolutions()); 

약간의 작업이 필요하지만 기본 아이디어를 볼 수 있습니다.

0

귀하의 서비스가 조회수에 대한 지식이 있어야한다고 생각하지 않습니다. 요구 사항이 변경 될 수 있으므로 이름을보기 이름에 연결하지 마십시오.

GetPuzzles()를 호출하면 루트 퍼즐 만로드해야하며 GetPuzzleById (int id)는 연결을 열망 할 수 있습니다.

는 기준 API의 예를 들면 : 당신이 게으른 부하를 캔트 이유 .SetFetchMode("Solutions", NHibernate.FetchMode.Join)

는 이해가 안 돼요. nHibernate를 사용하는 경우 프록시에 액세스 할 때 프록시가 데이터베이스로 돌아갑니다. 컨트롤러가 필요한 모든 데이터를 가져와야합니다. 로드되지 않은 프록시를 뷰에 전달하면 뷰가 데이터를로드 할 수없는 경우를 처리해야합니다.

그래서 내가 인터페이스를 바꿀 것, 컨트롤러, 당신이 필요로하는 데이터의 특정 부분을로드 사용자 만로드해야한다 등이이 방법에서 GetPuzzle(puzzleId,user)

할 수 있습니다 단지 열망 부하에 대한 데이터 한 명의 사용자.

+0

내 마음이 약간 희미하다. 나는 이것이 당신에게 의미가 있고 약간의 가치를 제공하기를 바랍니다. – JoshBerke

+0

세션이 GetPuzzle ... X() 메소드의 끝 부분에서 범위를 벗어날 때 게으르지 않습니다. 그것은 처분된다. 프록시가 항목을 나중에 가져 오려고하면 "세션이 이미 삭제되었습니다."오류가 발생합니다. – Micah