Car*_*ond 5 nhibernate asp.net-mvc
我在MVC 3 Web应用程序中使用NHibernate将来的查询,并试图在我的控制器中保持所有数据库访问,而不是在我的视图中.该站点是资源(描述性模糊)的目录,其具有多对多的成绩集合以及多对多的主题集合.用户选择一个或多个成绩,以及一个或多个主题,然后获取匹配资源的列表.
为了填充搜索表单,我正在使用将来的查询来获取所有成绩和主题:
public Domain.SearchFormData GetSearchFormData()
{
// Get all grades and all topics using a multiquery.
IEnumerable<Grade> grades = Session.QueryOver<Grade>()
.Future();
IEnumerable<Topic> topics = Session.QueryOver<Topic>()
.Future();
var result = new SearchFormData();
result.Grades = grades;
result.Topics = topics;
return result;
}
Run Code Online (Sandbox Code Playgroud)
这很简单,工作正常,并返回SearchFormData一个简单的DTO.此查询在控制器中执行,结果不需要任何进一步处理,因此它会直接传递到视图中以呈现为复选框列表.
但是由于未来查询的延迟执行,在视图开始迭代列表之前不会触发数据库访问.一些人(如NHibernate Profiler)认为这是一个禁忌,他们说,在视图开始渲染时,应该完成所有数据库访问.主要原因是,如果不这样做,很容易隐藏SELECT N + 1.
这不适用; 等级和主题都是没有集合的简单对象.我不介意该视图将触发数据库访问.但它让我寻找一种干净,清晰的方式来触发所有未来的查询.一种方法是访问结果,例如将其复制IEnumerable到列表中.但那不是我需要做的事情; 我只想执行排队查询.
我认为触发器在上面的查询之外发生是有意义的.我可能需要其他数据来呈现整个页面视图,我可能正在使用其他未来的查询来获取它.例如,主页还可能显示五个最受欢迎的资源和资源总数.然后控制器将调用多个方法来累积视图所需的内容,并且最有效的是一次执行所有这些方法.当然,人们做这种方式是扩大我GetSearchFormData进入GetAllHomePageData并与Home的页面上的所有字段返回DTO.但我使用搜索表单,而不仅仅是在主页上.所以我会以这种方式失去一些很好的模块化.
我认为最好的“解决方案”根本不是在视图模型类中使用 IEnumerable - 为什么不使用简单的数组?这将迫使您在控制器中完全填充模型,并且您不会失去 Linq 功能等。
第二个问题是您直接在 SearchFormData 中使用域实体(等级、主题) - 您应该使用 DTO。您提到 SearchFormData 是 DTO,但这并不完全正确,因为它引用了您的域实体。
所以 SearchFormData 应该看起来像这样:
public class SearchFormData
{
public GradeDTO[] Grades { get; set; }
public TopicDTO[] Topics { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
你真正的问题是与设计相关的问题,而不是 IMO 的 NHibernate Futures 问题。
| 归档时间: |
|
| 查看次数: |
1047 次 |
| 最近记录: |