Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's wrong with passing Linq2Sql objects to Views?

Tags:

asp.net-mvc

In a previous question, @Darin Dimitrov answered:

In your case the worst thing is that you are using your Linq2Sql models inside your views and that's one of the worst anti-patterns I see people doing in ASP.NET MVC applications. You absolutely should be using view models. That's what views should be passed from controllers and that's what controllers should get from views.

Why is it so bad to pass Linq2Sql objects as Models?

like image 624
Shaul Behr Avatar asked Jun 28 '11 16:06

Shaul Behr


2 Answers

There are a lot of reasons why it's bad to pass Linq2Sql objects as models to your views and controllers, and it would be relatively difficult to cover all of them in a single answer. So, here are my top 3:

Separation of Concerns - Linq2Sql objects have DAL logic embedded in them, which is a violation of SoC. Also, you will likely want to validate data passed from your views, which should be done in the Model (NOT the controller!). However, if you add this logic to your L2S models then you also violate SoC (not to mention the fact that your validations will be wiped out if you regenerate your L2S models)

Encapsulation - Your L2S classes have a lot of members that your view(s) and controller(s) likely do not need access to. A proper model would encapsulate these members to keep them inaccessible.

Maintainability and Reusability - At some point you may decide you want to change your backing store. If you use your L2S classes as models then you'll end up touching a LOT of code to make that change, whereas if you roll your own models then you'll only have to worry about changing your models and nothing else. Also, not messing with your L2S models (see SoC above) means that they're reusable across projects.

like image 150
Brian Driscoll Avatar answered Sep 20 '22 17:09

Brian Driscoll


In addition to Brian Driscoll's excellent answer, I would add that with LINQ to SQL or the Entity Framework, you don't always know what values actually exist on the objects you've been given. Let's say your view model included a User object from Linq2Sql. You may be tempted to do something like this:

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

Because the Messages property exists on the user object, it's easy to assume that this is totally fine. However, the results of this action aren't entirely clear.

  • If you have lazy loading enabled, but the context has been disposed, an exception will be thrown.
  • If you have lazy loading disabled, you'll probably end up with "Messages (0)"
  • If you have lazy loading enabled, and the context is active, this will cause every single message associated with that user to get loaded into memory, just to figure out how many there are.

On the other hand, if you used LINQ to generate a ViewModel that contains the information you know you'll need to generate your view, it might look like this:

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();
}

This uses a single SQL query to get all the information you'll need for this view, while ignoring any information you won't need (like the entire contents of the user's inbox). If some future developer wants to add information to this view, they're going to have to ensure it's populated on the ViewModel as part of the data-access logic.

like image 23
StriplingWarrior Avatar answered Sep 18 '22 17:09

StriplingWarrior