实体框架类与 POCO [英] Entity Framework classes vs. POCO

查看:30
本文介绍了实体框架类与 POCO的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对架构设计有普遍的不同意见,尽管不应使用 stackoverflow 来征求意见,但我还是想询问我将在下面描述的两种方法的优缺点:

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

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

如果数据库架构发生变化,我们会更新实体并在使用它的所有类中进行修改.

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

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

解决方案

我会使用中间类,即 POCO 而不是 EF 实体.

我认为直接使用 EF 实体的唯一优势是编写的代码更少...

使用 POCO 的优势:

您只公开您的应用程序实际需要的数据

基本上,假设您有一些 GetUsers 业务方法.如果您只想让用户列表填充网格(例如,您需要他们的 ID、姓名、名字),您可以这样写:

public IEnumerable获取用户(){返回 this.DbContext.用户.Select(z => new SimpleUser{ID = z.ID,名称 = z.Name,名字 = z.FirstName}).ToList();}

您的方法实际返回的内容非常清楚.现在想象一下,它返回了一个完整的 User 实体,其中包含您不想公开的所有导航属性和内部内容(例如 Password 字段)...>

它确实简化了使用您的服务的人的工作

对于Create 之类的业务方法而言,这一点更为明显.您当然不想使用 User 实体作为参数,让您的服务的消费者知道什么实际需要的属性会非常复杂...

想象以下实体:

公共类用户{公共长 ID { 获取;放;}公共字符串名称 { 获取;放;}公共字符串名字{获取;放;}公共字符串密码{获取;放;}public bool IsDeleted { 获取;放;}public bool IsActive { 获取;放;}公共虚拟 ICollection简介 { 得到;放;}公共虚拟 ICollection事件{得到;放;}}

使用void Create(User entity);方法需要哪些属性?

  • ID:不知道,可能是生成的,也可能不是
  • 姓名/名字:应该设置这些
  • 密码:那是纯文本密码还是散列版本?它是什么?
  • IsDeleted/IsActive:我应该自己激活用户吗?是通过商业方法完成的吗?
  • 个人资料:嗯……我如何影响用户的个人资料?
  • 事件:这到底是什么??

它迫使你使用延迟加载

是的,出于多种原因,我讨厌此功能.其中一些是:

  • 极其难以有效使用.我见过太多次产生数千个 SQL 请求的代码,因为开发人员不知道如何正确使用延迟加载
  • 异常难以管理.通过允许在任何时间(即延迟加载时)执行 SQL 请求,您将管理数据库异常的角色委托给上层,即业务层甚至应用程序.一个坏习惯.

使用 POCO 迫使您急切加载您的实体,更好的 IMO.

关于 AutoMapper

AutoMapper 是一种工具,可让您自动将实体转换为 POCO,反之亦然.我也不喜欢它.请参阅 https://stackoverflow.com/a/32459232/870604

I have a general difference of opinion on an architectural design and even though stackoverflow should not be used to ask for opinions I would like to ask for pros and cons of both approaches that I will describe below:

Details: - C# application - SQL Server database - Using Entity Framework - And we need to decide what objects we are going to use to store our information and use all throughout the application

Scenario 1: We will use the Entity Framework entities to pass all around through our application, for example the object should be used to store all information, we pass it around to the BL and eventually our WepApi will take this entity and return the value. No DTOs nor POCOs.

If the database schema changes, we update the entity and modify in all classes where it is used.

Scenario 2: We create an intermediate class - call it a DTO or call it a POCO - to hold all information that is required by the application. There is an intermediate step of taking the information stored in the entity and populated into the POCO but we keep all EF code within the data access and not across all layers.

What are the pros and cons of each one?

解决方案

I would use intermediate classes, i.e. POCO instead of EF entities.

The only advantage I see to directly use EF entities is that it's less code to write...

Advantages to use POCO instead:

You only expose the data your application actually needs

Basically, say you have some GetUsers business method. If you just want the list of users to populate a grid (i.e. you need their ID, name, first name for example), you could just write something like that:

public IEnumerable<SimpleUser> GetUsers()
{
    return this.DbContext
        .Users
        .Select(z => new SimpleUser
        {
            ID = z.ID,
            Name = z.Name,
            FirstName = z.FirstName
        })
        .ToList();
}

It is crystal clear what your method actually returns. Now imagine instead, it returned a full User entity with all the navigation properties and internal stuff you do not want to expose (such as the Password field)...

It really simplify the job of the person that consumes your services

It's even more obvious for Create like business methods. You certainly don't want to use a User entity as parameter, it would be awfully complicated for the consumers of your service to know what properties are actually required...

Imagine the following entity:

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; }
}

Which properties are required for you to consume the void Create(User entity); method?

  • ID: dunno, maybe it's generated maybe it's not
  • Name/FirstName: well those should be set
  • Password: is that a plain-text password, an hashed version? what is it?
  • IsDeleted/IsActive: should I activate the user myself? Is is done by the business method?
  • Profiles: hum... how do I affect a profile to a user?
  • Events: the hell is that??

It forces you to not use lazy loading

Yes, I hate this feature for multiple reasons. Some of them are:

  • extremely hard to use efficiently. I've seen too much times code that produces thousands of SQL request because the developers didn't know how to properly use lazy loading
  • extremely hard to manage exceptions. By allowing SQL requests to be executed at any time (i.e. when you lazy load), you delegate the role of managing database exceptions to the upper layer, i.e. the business layer or even the application. A bad habit.

Using POCO forces you to eager-load your entities, much better IMO.

About AutoMapper

AutoMapper is a tool that allows you to automagically convert Entities to POCOs and vice et versa. I do not like it either. See https://stackoverflow.com/a/32459232/870604

这篇关于实体框架类与 POCO的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆