实体框架类与POCO
本文关键字:POCO 框架 实体 | 更新日期: 2023-09-27 18:19:33
我对建筑设计有着普遍的意见分歧,尽管不应该使用stackoverflow来征求意见,但我想征求这两种方法的优缺点,我将在下面描述:
详细信息:-C#应用程序-SQL Server数据库-使用实体框架-我们需要决定我们将使用什么对象来存储我们的信息,并在整个应用程序中使用
场景1:我们将使用实体框架实体在我们的应用程序中传递所有信息,例如,该对象应用于存储所有信息,我们将其传递给BL,最终我们的WepApi将获取该实体并返回值。既没有DTO也没有POCO。
如果数据库模式发生更改,我们将更新实体并在使用它的所有类中进行修改。
场景2:我们创建一个中间类——称之为DTO或POCO——来保存应用程序所需的所有信息。有一个中间步骤,即获取存储在实体中并填充到POCO中的信息,但我们将所有EF代码保留在数据访问中,而不是跨所有层。
每种方法的优点和缺点是什么?
我会使用中间类,即POCO而不是EF实体。
我认为直接使用EF实体的唯一优势是编写的代码更少。。。
使用POCO的优点:
您只公开应用程序实际需要的数据
基本上,假设您有一些GetUsers
业务方法。如果你只想让用户列表填充一个网格(例如,你需要他们的ID、姓名、名字),你可以写这样的东西:
public IEnumerable<SimpleUser> GetUsers()
{
return this.DbContext
.Users
.Select(z => new SimpleUser
{
ID = z.ID,
Name = z.Name,
FirstName = z.FirstName
})
.ToList();
}
您的方法实际返回的结果非常清楚。现在想象一下,它返回了一个完整的User
实体,其中包含所有导航属性和您不想公开的内部内容(例如Password
字段)。。。
它确实简化了使用您服务的人员的工作
对于类似Create
的业务方法来说,这一点更为明显。您当然不想使用User
实体作为参数,对于您的服务的消费者来说,要知道实际需要什么属性将非常复杂。。。
想象一下以下实体:
public class User
{
public long ID { get; set; }
public string Name { get; set; }
public string FirstName { get; set; }
public string Password { get; set; }
public bool IsDeleted { get; set; }
public bool IsActive { get; set; }
public virtual ICollection<Profile> Profiles { get; set; }
public virtual ICollection<UserEvent> Events { get; set; }
}
使用void Create(User entity);
方法需要哪些属性?
- ID:不知道,也许是生成的,也许不是
- Name/FirstName:这些应该设置
- 密码:这是纯文本密码,还是散列版本?它是什么
- IsDeleted/IsActive:我应该自己激活用户吗?是通过商业方法完成的吗
- 配置文件:嗯…我如何影响用户的配置文件
- 事件:那是什么
它迫使您而不是使用延迟加载
是的,我讨厌这个功能有多种原因。其中一些是:
- 极难有效使用。由于开发人员不知道如何正确使用延迟加载,我已经看到过太多次生成数千个SQL请求的代码
- 极难管理异常。通过允许SQL请求在任何时候执行(即当您延迟加载时),您将管理数据库异常的角色委派给上层,即业务层甚至应用程序。一个坏习惯
使用POCO迫使你急于加载你的实体,更好的IMO.
关于AutoMapper
AutoMapper是一个允许您自动将实体转换为POCO的工具,反之亦然。我也不喜欢。看见https://stackoverflow.com/a/32459232/870604
我有一个反问题:为什么不两者都
考虑任意MVC应用程序。在模型和控制器层中,通常需要使用EF对象。如果您使用"代码优先"定义它们,那么您基本上已经定义了它们在应用程序中的使用方式首先,然后设计了持久层以准确地保存应用程序中所需的更改。
现在考虑将这些对象提供给"视图"层。视图可能反映您的对象,也可能不反映您的工作对象的聚合。这通常会导致POCOS/DTO捕获视图中需要的任何内容。另一种情况是希望在web服务中发布对象。许多框架在poco类上提供了简单的序列化,在这种情况下,您通常需要1)注释EF类或2)制作DTO。
还要注意,当您使用POCOS或关闭上下文时,EF类上可能存在的任何延迟加载都会丢失。