将Linq2Sql对象传递给Views有什么问题?

时间:2011-06-28 16:20:19

标签: asp.net-mvc

previous question,@ Darin Dimitrov answered

  

在你的情况下,最糟糕的是   您正在使用Linq2Sql模型   在你的观点内,这是一个   我看到人们最糟糕的反模式   在ASP.NET MVC应用程序中执行。您   绝对应该使用视图   楷模。这就是观点应该是什么   从控制器传递而来   控制器应该从哪里获得   视图。

为什么将Linq2Sql对象作为模型传递它是如此糟糕?

3 个答案:

答案 0 :(得分:5)

将Linq2Sql对象作为模型传递给视图和控制器是很糟糕的原因有很多,并且在单个答案中覆盖所有这些对象相对困难。所以,这是我的前三名:

关注点分离 - Linq2Sql对象中嵌入了DAL逻辑,这违反了SoC。此外,您可能希望验证从视图传递的数据,这应该在模型中完成(不是控制器!)。但是,如果您将此逻辑添加到L2S模型,那么您也违反了SoC(更不用说如果重新生成L2S模型,您的验证将被删除)

封装 - 您的L2S类有很多成员,您的视图和控制器可能不需要访问。一个合适的模型将封装这些成员以使其无法访问。

可维护性和可重用性 - 在某些时候,您可能决定要更改后备存储。如果你使用你的L2S类作为模型,那么你最终会触摸很多代码来进行更改,而如果你推出自己的模型,那么你只需要担心改变你的模型而不需要其他任何东西。另外,不要弄乱你的L2S模型(参见上面的SoC)意味着它们可以在各个项目中重复使用。

答案 1 :(得分:4)

除了Brian Driscoll的优秀答案之外,我还要在LINQ to SQL或Entity Framework中添加它,你并不总是知道你给出的对象上实际存在哪些值。假设您的视图模型包含来自Linq2Sql的User对象。你可能想做这样的事情:

Messages (<%: Model.User.Messages.Count() %>)

因为用户对象上存在Messages属性,所以很容易认为这是完全正常的。但是,这一行动的结果并不完全清楚。

  • 如果启用了延迟加载,但上下文已被释放,则会抛出异常。
  • 如果您禁用了延迟加载,则可能最终会使用“Messages(0)”
  • 如果启用了延迟加载,并且上下文处于活动状态,这将导致与该用户关联的每条消息都被加载到内存中,只是为了确定有多少消息。

另一方面,如果您使用LINQ生成一个ViewModel,其中包含您知道生成视图所需的信息,它可能如下所示:

using (var context = _contextFactory.Get()) {
    return (from u in context.Users
            where u.UserId == userId
            select new UserSummary {Name = u.Name, MessageCount = u.Messages.Count())
           .Single();
}

这使用单个SQL查询来获取此视图所需的所有信息,同时忽略您不需要的任何信息(例如用户收件箱的全部内容)。如果未来某个开发人员想要向此视图添加信息,他们将不得不确保它作为数据访问逻辑的一部分填充在ViewModel上。

答案 2 :(得分:1)

不仅Linq-To-Sql对象,而且任何实体对象都不应该暴露给视图。

  1. 它向最终用户显示您的数据架构(黑客可能会觉得它很有用)

  2. 它违反了mvc中的关注分离原则。

  3. 当您的实体在视图中对象延迟加载时,在视图中使用数据访问逻辑并没有太大的不同。因此,分层应用程序的重点已经一去不复返了。