ASP.NET MVC - Database entities or ViewModels?

2019-02-03 00:01发布

I am currently working on an ASP.NET MVC project.

Some developers on the team want to bind the auto-generated database entities directly to the Views.

Other developers want to create tailor-made ViewModel's and bind those to the Views.

Objectively, what are the pros and cons of both approaches?

(By "database entities" I am referring to the auto generated classes that an ORM framework generates, such as LINQ to SQL, Entity Framework or LLBLGen).

8条回答
闹够了就滚
2楼-- · 2019-02-03 00:27

Using DB entities in your views, especially your forms is a massive security issue. Take the following POCO object

public class User
{
    public int Id { get; set; }
    public string Username { get; set; }
    public string Email { get; set; }
    public bool IsAdmin { get; set; }
}

Now say you are presenting a view that allows a user to change their email. The MVC method for processing the form result when using Db Entities instead of view models would look like: (unless you don't use model binding, in which case you are making more work for yourself)

public class HomeController : Controller
{
    [HttpPost]
    public ActionResult ChangeEmail(User user)
    {
        //....
    }
}

Model binding in Asp.net works by looking for GET or POST parameters matching the names of the properties in the model. Therefore, all the user has to do is add IsAdmin=true to the POSt parameters and viola, the model passed into the ChangeEmail function will have the IsAdmin property set to true, which could very easily be accidentally added into the database, giving users free access to change data they didn't have access to change.

This goes for user permissions, changing who owns an entity (make your question be associated with me instead of you), change original creation dates, etc...

查看更多
劳资没心,怎么记你
3楼-- · 2019-02-03 00:29

The orthodoxy is that you should never use your raw database entities in your views. Like any rule, it is there to be broken if you know your entities well and you understand the consequences, but there are very good reasons not to break that rule, particularly when working in teams and with code that will be maintained in future by people who might not understand the rule or the entities as well as you do. The main reasons are:

  1. ORM lazy loading. Imagine your Customer has a lazy loaded collection Orders. You pass Customer off to the View and it iterates over Orders. You get an N*1 select on the Orders table. But it also means that your database connection still needs to be open in the View. There is a pattern that people use 'Transaction per Action' which disposes of the database context in the Action_Executed event, which happens before your View is rendered. So you could be trying to access the database after it has been disposed. Even if you are not doing that now, someone in future might decide to implement that pattern because it is fashionable.

  2. The concerns of the ViewModel are different to the db Model. For example, you typically decorate your ViewModel properties with validation attributes. These typically are different or only concern the UI not the db. If you bind to your database entities you will find all these UI concerns polluting you DB entities.

  3. Related to 2 - the requirements of the ViewModel may demand computed or derived properties. For example, a Fullname constructed from First and Last names. These kind of things are best kept in the ViewModel.

  4. You can unit-test your ViewModels in isolation from the database. ViewModels can end up containing quite a lot of logic which needs to be unit-tested. This is easier to test if it is not tied to your database (as with EF entities).

In general, creating and maintaining ViewModels (even without AutoMapper) is not an overhead and you will find it is a much better pattern of development overall. I would recommend it for everything but the simplest cases (lookup lists of static data, for example).

查看更多
登录 后发表回答