将EntityObjects用作模型(MVC)是一种好习惯吗?

Sha*_*ica 12 c# asp.net-mvc entity-framework asp.net-mvc-4 entity-framework-5

我正在使用Entity Framework 5构建我的第一个MVC 4/Razor Web应用程序,并在做出任何设计决策之前做了一些功课.

我看到EF对象来自EntityObject,它似乎有很多有用的最佳实践构建它,其中最重要的是乐观的并发处理.换句话说,如果2人同时装载123枫树街的简·多伊的纪录,第一个改变了她的名字简·史密斯,第二个改变了她的地址,以321枫树街,那么它很容易让被合并方面的变化在没有冲突的情况下进入记录,而第二个用户尝试修改与第一个用户相同的字段将导致错误.

在另一方面,它似乎是相当标准的做法是创建轻量级数据传输对象的服务器和客户端,并作为或型号为MVC框架之间传递数据.这对于确保最小的客户端流量非常有用,但它会破坏并发检查.

所以我质疑使用DTO的理由.使用DTO的原因是什么?使用EntityObjectas或MVC模型有多糟糕?如上所述,您建议采用哪种其他解决方案来实现乐观并发处理?

Plu*_*luc 10

=发表评论为answer =

从几个版本开始,EF对象就是POCO(不确定是哪个).如果你想要一个"EntityObject",你必须使用某种适配器(我相信有一个适合迁移的应用程序,但我不建议将它作为新项目的一部分使用).

如果你的模型类有EF相关的方法,那么这是非常糟糕的.但EF 5不应该.从4.1开始,我相信,他们使用Proxies而不是为了这个原因而完全扩展EntityObject - 将它们作为模型使用是一种很好的做法.

只需看看你的.tt和生成的.cs文件.他们是普通的POCO.没有接口,没有基类.如果你从实体框架中获取一个对象并检查对象的类型,你会发现类似的东西System.Data.Entity.DynamicProxies.Employee_5E43C6C196[...].这是代理生成的类.但是,如果您执行完全相同的操作但在(dbContext.Configuration.ProxyCreationEnabled = false;)之前更改数据库上下文配置,那么您已经为自己赢得了一个很好的Employee实体!

因此,回答原始问题,将EF POCO用作模型是完全可接受的/良好实践,但要确保将它们用作非持久对象.

附加信息

您应该考虑DDD概念和DDD兼容模式的实现,例如存储库或您认为可以使用的任何内容.

您不应该直接在视图中使用这些实体,持久性或非持久性.

您应该阅读有关AutoMapper的信息,以便让您的生活更轻松(与存储库或独立产品配合使用).它将方便从ProxyEmployee - > Employee - > ViewModel和相反的转移.

EF实体的可怕使用示例:

return View(dbContext.employees.First());
Run Code Online (Sandbox Code Playgroud)

EF实体的错误#1使用示例:

Employee e = dbContext.employees.First();
return View(new Employee { name = e.name, [...] });
Run Code Online (Sandbox Code Playgroud)

EF实体的错误#2使用示例:

Employee e = dbContext.employees.First();
return View(new EmployeeViewModel{ employee = e });
Run Code Online (Sandbox Code Playgroud)

EF实体的正常使用示例:

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

EF实体的良好使用示例:

Employee e = dbContext.employees.First();
EmployeeViewModel evm = Mapper.Map<Employee, EmployeeViewModel>(e);
return View(evm);
Run Code Online (Sandbox Code Playgroud)

EF实体的真实使用示例:

Employee e = employeRepository.GetFirstEmployee();
EmployeeViewModel evm = Mapper.Map<Employee, EmployeeViewModel>(e);
return View(evm);
Run Code Online (Sandbox Code Playgroud)

如何查克·诺里斯会做到这一点:

return View(EmployeeViewModel.Build(employeRepository.GetFirstEmployee()));
Run Code Online (Sandbox Code Playgroud)

  • 如果我为Chuck Norris说+1,你会举报我吗?如果是这样,那么我说整个答案+1(这是我倾向于做的,无论如何):) (2认同)
  • 查克诺里斯让你做到了.(PS.我喜欢Shaul编辑我的帖子来修复Chuck Norris拼写中的拼写错误) (2认同)

Kri*_*aes 7

EntityObject直接传递给视图时我只看到坏点:

  • 您需要进行手动白名单或黑名单,以防止过度发布和批量分配
  • 从视图中意外延迟加载额外数据变得非常容易,导致选择N + 1个问题
  • 在我个人看来,模型应该紧密地组合视图上显示的信息,并且在大多数情况下(除了基本的CRUD东西),视图包含来自多个的信息 EntityObject