2009-06-22 74 views
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); 
} 

后来的拼图视图我现在只关心当前用户的解决方案。我不想使用所有解决方案和所有步骤加载整个图表。

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. 
} 

里面我IPuzzleService,我的方法是这样的:

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

我有一个类似的情况,我不能使用延迟加载。

如果您只需要一个或两个案例,那么您建议的最简单的方法是创建单独的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 2009-06-22 15:26:22