Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it good practice to use EntityObjects as a Model (MVC)?

I'm building my first MVC 4/Razor web app using Entity Framework 5, and doing a bit of homework before making any design decisions.

I see that the EF objects descend from EntityObject, which appears to have a lot of useful best-practices stuff built it, not least of which is optimistic concurrency handling. In other words if 2 people load the record of Jane Doe of 123 Maple Street simultaneously, the first one changes her name to Jane Smith and the second one changes her address to 321 Maple Street, then it's very easy to allow both changes to be merged into the record without conflicts, while an attempt by a second user to modify the same field as the first user will result in an error.

On the other hand, it seems pretty standard practice to create lightweight Data Transfer Objects to pass data between the server and the client, and which serve as or in models for the MVC framework. This is great for ensuring minimal traffic to the client, but it screws up concurrency checking.

So I'm questioning the rationale for using DTOs. What are the reasons for using DTOs? How bad is it to use an EntityObject as or within a MVC model? What other solution would you propose to enable optimistic concurrency handling as I've described above?

like image 478
Shaul Behr Avatar asked Oct 11 '12 11:10

Shaul Behr


2 Answers

=Posting comment as answer=

EF objects are POCOs since a couple versions ago (not sure which). If you want an "EntityObject", you have to use some sort of adapter (I beleive there is one to facilitate application migration, but I wouldn't recommend using it as part of a new project).

If your model classes has EF related methods, then yes it's really bad to do so. But EF 5 shouldn't. Since 4.1, I believe, they use Proxies instead of extending EntityObject exactly for that reason - to make it a good practice to use them as Models.

Just look at your .tt and generated .cs files. They are plain POCOs. No interfaces, no base classes. If you get an object from entity framework and check the object's type, you will find something like System.Data.Entity.DynamicProxies.Employee_5E43C6C196[...]. This is the class generated by the proxy. However, if you do the exact same thing but change the database context configuration before (dbContext.Configuration.ProxyCreationEnabled = false;), you've earned yourself a nice Employee entity!

So, to answer to original question, it is completly acceptable / good practice to use EF POCOs as Models but make sure you use them as non-persistent objects.

Additional information

You should consider DDD concepts and the implementation of a DDD complient paterns such as repositories or anything you feel comfertable using.

You should never use those entities directly in views, persistent or none-persistent.

You should read about AutoMapper to make your life easier (goes nicely with repositories or stand-alone). It will facilitate the transfer from ProxyEmployee -> Employee -> ViewModel and the opposite.

Example of horrible usage of EF entities:

return View(dbContext.employees.First());

Example of bad #1 usage of EF entities:

Employee e = dbContext.employees.First();
return View(new Employee { name = e.name, [...] });

Example of bad #2 usage of EF entities:

Employee e = dbContext.employees.First();
return View(new EmployeeViewModel{ employee = e });

Example of ok usage of EF entities:

Employee dbEmploye = dbContext.employees.First();
Employee e = new Employee { name = dbEmploye.name, [...] };
return View(new EmployeeViewModel { employee = e });

Example of good usage of EF entities:

Employee e = dbContext.employees.First();
EmployeeViewModel evm = Mapper.Map<Employee, EmployeeViewModel>(e);
return View(evm);

Example of awesome usage of EF entities:

Employee e = employeRepository.GetFirstEmployee();
EmployeeViewModel evm = Mapper.Map<Employee, EmployeeViewModel>(e);
return View(evm);

How Chuck Norris would do it:

return View(EmployeeViewModel.Build(employeRepository.GetFirstEmployee()));
like image 180
Pluc Avatar answered Oct 05 '22 22:10

Pluc


I only see bad points when passing an EntityObject directly to a view:

  • You need to do manual whitelisting or blacklisting to prevent over-posting and mass assignment
  • It becomes very easy to accidentally lazy load extra data from your view, resulting in select N+1 problems
  • In my personal opinion, a model should closely resembly the information displayed on the view and in most cases (except for basic CRUD stuff), a view contains information from more than one EntityObject
like image 45
Kristof Claes Avatar answered Oct 05 '22 23:10

Kristof Claes