EF6 和 EF Core 之间的行为变更
下面是包含 EF6 和 EF Core 之间的行为变更的非完整列表。 移植应用程序时,务必牢记它们,因为这些可能会更改应用程序的行为方式,而在交换到 EF Core 后它们不会显示为编译错误。
它用作迁移过程中需要考虑的概要检查事项。 有关更详细的逐个案例说明,请阅读详细案例。
DbSet.Add/Attach 和图形行为
在 EF6 中,在实体上调用 DbSet.Add()
将递归搜索导航属性引用的所有实体。 所找到的上下文未在跟踪的任何实体也会被标记为“已添加”。 DbSet.Attach()
的行为相同,但会将所有实体标记为“未更改”。
EF Core 执行相似的递归搜索,但有些规则略有不同。
- 如果为生成的密钥配置了根实体,并且未设置密钥,则会将该实体置于
Added
状态。 - 适用于递归搜索导航属性期间找到的所有实体:
- 若实体的主键由存储生成
- 若主键未设置为值,状态将设置为“已添加”。 若为主键值的属性类型分配了 CLR 默认值(如为
int
分配0
,为string
分配null
等),则视为“未设置”它。 - 若主键设置为值,状态将设置为“未更改”。
- 若主键未设置为值,状态将设置为“已添加”。 若为主键值的属性类型分配了 CLR 默认值(如为
- 若主键非由数据库生成,则将实体置于与根相同的状态。
- 若实体的主键由存储生成
- 此行为变更仅适用于
Attach
和Update
方法组。Add
始终将实体置于Added
状态,即使设置了密钥也是如此。 Attach
方法将设置了密钥的实体置于Unchanged
状态。 这有助于实现“如果为新则插入它,否则不管它。”Update
方法将设置了密钥的实体置于Modified
状态。 这有助于实现“如果为新则插入它,否则更新它。”
此处的一般理念是,Update
是处理断开连接实体的插入和更新的一种非常简单的方法。 它可确保插入任何新实体,并更新任何现有实体。
同时,Add
还提供了一种简单的强制插入实体的方式。 仅当不使用存储生成的密钥时,添加功能最为有用,因为在这种情况下 EF 不知道实体是否为新实体。
有关 EF Core 中的这些行为的详细信息,请参阅 EF Core 中的变更跟踪。
Code First 数据库初始化
EF6 包含许多关于执行数据库连接和数据库初始化的功能。 这些规则包括:
- 若未执行任何配置,EF6 将从 SQL Express 或 LocalDb 选择数据库。
- 若应用程序的
App/Web.config
文件中包含与上下文名称相同的连接字符串,则将使用此连接。 - 如果数据库不存在,则会创建一个。
- 若数据库中不存在模型中的任何表,则会将当前模型的架构添加到数据库。 若启用了迁移,则会使用它们创建数据库。
- 若数据库存在,并且 EF6 此前已创建架构,则将检查架构是否与当前模型兼容。 若在创建架构后模型已更改,将引发异常。
EF Core 不执行任何此类功能。
- 必须在代码中显式配置数据库连接。
- 不执行初始化。 必须使用
DbContext.Database.Migrate()
应用迁移(或使用DbContext.Database.EnsureCreated()
/EnsureDeleted()
创建/删除数据库,而不使用迁移)。
Code First 表命名约定
EF6 通过复数形式服务运行实体类名,来评估实体映射到的默认表名称。
EF Core 使用派生的上下文上公开实体的 DbSet
属性的名称。 若实体不包含 DbSet
属性,则使用类名。
有关详细信息,请阅读管理数据库架构。