实体框架类与POCO

本文关键字:POCO 框架 实体 | 更新日期: 2023-09-27 18:19:33

我对建筑设计有着普遍的意见分歧,尽管不应该使用stackoverflow来征求意见,但我想征求这两种方法的优缺点,我将在下面描述:

详细信息:-C#应用程序-SQL Server数据库-使用实体框架-我们需要决定我们将使用什么对象来存储我们的信息,并在整个应用程序中使用

场景1:我们将使用实体框架实体在我们的应用程序中传递所有信息,例如,该对象应用于存储所有信息,我们将其传递给BL,最终我们的WepApi将获取该实体并返回值。既没有DTO也没有POCO。

如果数据库模式发生更改,我们将更新实体并在使用它的所有类中进行修改。

场景2:我们创建一个中间类——称之为DTO或POCO——来保存应用程序所需的所有信息。有一个中间步骤,即获取存储在实体中并填充到POCO中的信息,但我们将所有EF代码保留在数据访问中,而不是跨所有层。

每种方法的优点和缺点是什么?

实体框架类与POCO

我会使用中间类,即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类上可能存在的任何延迟加载都会丢失。