实体框架 - 类型

在实体框架中,有两种类型的实体允许开发人员将自己的自定义数据类与数据模型一起使用,而无需对数据类本身进行任何修改。

  • POCO 实体
  • 动态代理

POCO 实体

  • POCO 代表"普通"CLR 对象,可用作数据模型的现有域对象。

  • 映射到实体的 POCO 数据类在数据模型中定义。

  • 它还支持与实体数据模型工具生成的实体类型相同的大多数查询、插入、更新和删除行为。

  • 您可以使用 POCO 模板从概念生成持久性无关的实体类型模型。

让我们看一下以下概念实体数据模型的示例。

概念实体模型

要为上述实体模型生成 POCO 实体 −

步骤 1 − 右键单击​​设计器窗口。它将显示以下对话框。

设计器窗口

步骤 2 − 选择添加代码生成项...

代码生成

步骤 3 −选择 EF 6.x DbContext 生成器,输入名称,然后单击"添加"按钮。

您将在解决方案资源管理器中看到生成了 POCODemo.Context.tt 和 POCODemo.tt 模板。

Solution Explorer

POCODemo.Context 生成 DbContext 和对象集,您可以返回它们并用于查询,例如上下文、学生和课程等。

Generate

另一个模板处理所有类型 Student、Courses 等。以下是从实体模型自动生成的 Student 类的代码。

namespace ConsoleApplication1 {

   using System;
   using System.Collections.Generic;

   public partial class Student {

      [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", 
         "CA2214:DoNotCallOverridableMethodsInConstructors")]

      public Student() {
         this.Enrollments = new HashSet<Enrollment>();
      }

      public int ID { get; set; }
      public string LastName { get; set; }
      public string FirstMidName { get; set; }
      public System.DateTime EnrollmentDate { get; set; }

      [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", 
         CA2227:CollectionPropertiesShouldBeReadOnly")]

      public virtual ICollection<Enrollment> Enrollments { get; set; }

   }
}

从实体模型为课程和招生表生成类似的类。

动态代理

在创建 POCO 实体类型的实例时,实体框架通常会创建动态生成的派生类型的实例,作为实体的代理。也可以说它是一个运行时代理类,就像 POCO 实体的包装类一样。

  • 您可以覆盖实体的某些属性,以便在访问属性时自动执行操作。

  • 此机制用于支持关系的延迟加载和自动更改跟踪。

  • 此技术也适用于使用 Code First 和 EF Designer 创建的模型。

如果您希望实体框架支持相关对象的延迟加载并跟踪 POCO 类中的更改,则 POCO 类必须满足以下要求 −

  • 自定义数据类必须声明为具有公共访问权限。

  • 自定义数据类不得密封。

  • 自定义数据类不得是抽象的。

  • 自定义数据类必须具有不具有以下属性的公共或受保护的构造函数参数。

  • 如果希望使用 CreateObject 方法为 POCO 实体创建代理,请使用不带参数的受保护构造函数。

  • 调用 CreateObject 方法并不能保证创建代理:POCO 类必须遵循本主题中描述的其他要求。

  • 该类无法实现 IEntityWithChangeTracker 或 IEntityWithRelationships 接口,因为代理类实现了这些接口。

  • ProxyCreationEnabled 选项必须设置为 true。

以下示例是动态代理实体类。

public partial class Course {

   public Course() {
      this.Enrollments = new HashSet<Enrollment>();
   }

   public int CourseID { get; set; }
   public string Title { get; set; }
   public int Credits { get; set; }
	
   public virtual ICollection<Enrollment> Enrollments { get; set; }
}

要禁用创建代理对象,请将 ProxyCreationEnabled 属性的值设置为 false。