ASP MVC:服务应该返回 IQueryable 的吗?
Posted
技术标签:
【中文标题】ASP MVC:服务应该返回 IQueryable 的吗?【英文标题】:ASP MVC: Should services return IQueryable's? 【发布时间】:2011-01-13 23:26:39 【问题描述】:你怎么看?您的 DAO 是否应该返回一个 IQueryable 以在您的控制器中使用它?
【问题讨论】:
【参考方案1】:没有。您的控制器根本不应该处理任何复杂的逻辑。保持苗条;模型(不是 DAO)应该把它需要传递给视图的所有东西交给控制器。
在 Controller 类中看到查询(甚至可查询)我认为是代码异味。
【讨论】:
谢谢亚伦,很好。尽管如此,使用 IQueryable 还是有一些优势,例如服务的灵活性和可维护性——因为使用管道和过滤器模式,DAO 接口的增长会减少。你怎么看? 意大利面条式代码总是似乎在项目年轻且规模较小时更易于维护;但是,随着项目的发展,您会开始后悔没有明确分离关注点。 传递您的 IQueryableIQueryable
周围踢球或对数据库有任何了解如何?它完全打破了领域模型提供的封装。 (你确实有一个领域模型,对吧?)
不,我有一个持久性模型。如果我的回答中两种操作方法 sn-ps 之间的区别是一种“干净”而另一种是意大利面条,那么您对意大利面条代码的标准非常低。【参考方案2】:
目前听起来很有吸引力,但是really isn't。
【讨论】:
【参考方案3】:我喜欢将 IQueryable 传递给我的控制器,因为在我的应用开发的整个生命周期中,我不必在每个 DAO 方法和接口中创建蹩脚的分页和排序方法。
GetCustomersByLastname( string lastname )
迅速变成
GetCustomersByLastname( string lastname, string sortcolumn, int pagesize, int page )
一次又一次,一次又一次。擦!
使用 IQueryable,您可以以正交方式实现分页和排序,例如利用 IPagedList 项目。返回 IQueryable 还可以让您轻松访问总对象 .Count() ,而不会对您的数据层产生更多反常。
@Robert 的 IQueryable 等于胖控制器的参数非常不稳定。 Fat 控制器类似于过去臃肿的 .aspx.cs 页面。如果您所做的只是连接到您的 DAL,然后将结果从您的查询技术中获得“肥胖”,那么您可以通过在单个类中塞入大量逻辑来获得它。除非您开始在内部滚动日志记录、通知和其他正交关注点,否则您不会因为您的数据访问方法而获得胖控制器。
public ActionResult Detail( string searchTerm )
var model = MyDAL.MyObjects( searchTerm );
对比:
public ActionResult Detail( string searchTerm )
var model = MyDAL.MyObjects.Where( x => x.Name == searchTerm );
我看不出有什么明显的区别。
@Mark Seemann 的回答同样不稳定。当然,您可以在项目中间更改整个数据层,但无论您多么抽象,这都将是一场复杂的灾难。他使用的示例是从 Linq2Sql 切换到 Windows Azure 的表存储。 RDBMS 到键/值存储?痛点是您的存储库实施?从 RDBMS 到 Key/Value 存储将是一些疯狂的事情,无论如何这将是可怕的。
Mark 在他的论点中还提到了领域驱动设计。那是您建筑的系统类型吗?是否有足够的“领域”而不是纯粹的 CRUD 场景使这种方法有价值?如果不是那么为什么要打扰?
无论如何,使用 LINQ 和 IQueryable 接口可以减少切换数据层的痛苦。如果您在支持 LINQ 和 IQueryableProvider(我认为这就是名称)的 ORM 之间切换,那么只有下游代码才关心该更改。您的控制器将保持与现在市场上大多数 ORM 之间的相同切换。
【讨论】:
如果这样做的目的是排序和分页,那么这可以通过包装IQueryable<T>
但仍输出域模型的IPager<T>
接口轻松完成。我使用这种方法,它只需要很少的代码,并且消除了控制器和数据库之间的任何直接交互。你的比较很奇怪;似乎您的项目缺少域模型,在这种情况下,当然没有太大区别 - 但如果您没有域模型,那么您实际上没有 MVC。
另外请注意,使用IQueryable<T>
完成的任何分页(我猜这是OrderBy
和Skip
的组合)将是低效的。虽然使用它可能更方便,但有效的分页通常需要使用原始 SQL 或存储过程,它们都不适合 IQueryable<T>
过滤器/投影。
@Aaronaught 您的第二条评论是错误的。所有启用 Linq 的.Net ORMS 使用 .Skip() 和 .Take() 从 IQueryable如果您遵循“胖模型,瘦控制器”范式,那么就不会。
在Fat Controller anti-pattern 上查看此帖子。
【讨论】:
以上是关于ASP MVC:服务应该返回 IQueryable 的吗?的主要内容,如果未能解决你的问题,请参考以下文章
MVC / LINQ /合并Iqueryable对象[关闭]
asp.net mvc中使用linq to sql查询数据集(IQueryable类型) 怎么用foreach循环去数据集的数据?