当有人在写一个更有用的答案时,我会很快解决你的观点。
Model
是您要显示的数据。
通常,您会希望使用对象关系映射,以便您的大多数业务对象类对应于数据库表,而您不必手动构造查询。
有很多可用的 ORM 解决方案,包括实体框架、NHibernate 和(现在正在死去的)LINQ to SQL。
还有一个很棒的 micro-ORM,称为Dapper,如果更大的框架对您的解决方案感到不必要的臃肿,您可能会喜欢它。
确保您了解它们之间的差异。
DAL 在 .NET 中比“知道”如何加载自己的类更惯用。
(虽然在实践中你的解决方案很可能是两种方法的混合——关键是,像往常一样,保持平衡。)
我的建议是,只要你的 ORM 允许并且不会给调用代码增加额外的复杂度, 就尽量让你的模型保持普通的旧 CLR 对象。
这些对象,只要有可能(并且是明智的——任何规则都有例外!),不应该绑定到特定的数据库或 ORM 实现。
如果需要,将您的代码迁移到另一个 ORM 将只是重写数据访问层的问题。
但是,您应该明白,这不是分离 DAL 的主要原因。
您不太可能在项目中间更改 ORM,除非您最初的选择确实不适合该目的,或者您突然吸引了 100,000 名用户并且您的 ORM 无法处理它。一开始就对此进行优化是非常愚蠢的,因为它会分散您的注意力,使您无法创建能够吸引您正在优化的点击量的一小部分的出色产品。(免责声明:我以前走过这条路。)
相反,DAL 的好处是您的数据库访问变得总是明确的并且被限制在您希望它发生的某些地方。例如,接收到要显示的模型对象的视图不会试图从数据库中加载某些内容,因为实际上这是控制器的工作。
将诸如业务逻辑、表示逻辑和数据库逻辑之类的东西分开通常也很好。很多时候,它会产生更好、更少错误的代码。另外:您可能会发现很难对依赖于从数据库加载的对象的任何代码进行单元测试。另一方面,使用 LINQ 创建一个“假”的内存数据访问层是微不足道的。
请记住,这条规则也有例外,例如由许多 ORM 生成的惰性属性,它们会在运行中加载关联的对象——即使在视图中调用也是如此。因此,重要的是您应该做出明智的决定,何时允许数据访问以及为什么。语法糖可能很有用,但如果您的团队不知道从 ORM 加载 20,000 个对象的性能影响,这将成为一个问题。
在使用任何 ORM 之前,请先了解它是如何工作的。
在 Active Record 风格的对象和 DAL 之间进行选择主要取决于品味、.NET 中的常见习语、团队习惯以及 DAL 最终可能不得不被替换的可能性。
最后,ViewModel
s 是另一种野兽。
试着这样想它们:
- 视图中不应该有任何比
if-then-else
.
- 然而,在展示事物时往往有一些复杂的逻辑。
考虑分页、排序、在一个视图中组合不同的模型、了解 UI 状态。
这些是视图模型可以处理的事情。
在简单的情况下,它只是将几个不同的模型组合成一个“视图模型”:
class AddOrderViewModel {
// So the user knows what is already ordered
public IEnumerable<Order> PreviousOrders { get; set; }
// Object being added (keeping a reference in case of validation errors)
public Order CurrentOrder { get; set; }
}
模型只是数据,控制器组合数据并引入一些逻辑来描述要在视图模型中显示的数据,而视图只是呈现视图模型。
视图模型也可以作为一种文档。他们回答了两个问题:
- 我可以在视图中使用哪些数据?
- 我应该在控制器中准备哪些数据?
不要将对象传递到ViewData
并记住它们的名称和类型,而是使用通用视图并将内容放入ViewModel
的属性中,这些属性是静态类型的,可用于 IntelliSense。
此外,您可能会发现创建ViewModel
层次结构很有用(但不要走极端!)。例如,如果您的站点范围的导航从面包屑更改为其他内容,那么只需替换基本视图模型上的属性、显示它的局部视图以及在基本控制器中构造它的逻辑就很酷。保持理智。