当标识列不唯一时,entity framework会错误地映射数据

没有进入“为什么”,只需了解inheritance和我必须使用的:)

我有一个映射到视图的EF6 edmx。 其上没有标识列,因此为了使EF映射实体,选择第一个非空列作为PK。 这背后的原始想法是只读它不会更新或删除。 没有过滤(ODATA位于此之上), 唯一的 – 我只是意味着 – 使用的方式是从实体中select top N *

视图中有4条记录。

 TypeCode | Contact | UserID | LocaleID | EntityName --------------------------------------------------------- 1 6623 1032 9 Jane 1 6623 1032 9 Jane 1 6623 1032 9 John 1 6623 1032 9 John 

我看到的问题是EF将所有4行映射相同。 上面所有“约翰”的名字都变成了“简”

好的,抛开设计决策,并且视图上没有识别记录,为什么EF映射最后两行错误? 我最初的想法是,因为“PK”被设置为TypeCode它不知道如何做到这一点。 但是,为什么只在从数据库中读取结果时才使用键列? 我原以为它只对更新和删除很重要

如果按entity framework查询数据,则默认行为是每个实体化实体都由其唯一键跟踪。 唯一键由您告知EF用作键的任何属性组成,或者,它推断为键属性(在您的情况下为TypeCode )。 每当重复的实体密钥尝试进入更改跟踪器时,就会抛出一个错误,告知该对象已被跟踪。

因此,EF根本无法实现具有重复主键值的对象。 它会损害其跟踪机制。

看来,至少在AsNoTracking()中, AsNoTracking()可以用作解决方法。 AsNoTracking告诉EF只是在不跟踪它们的情况下实现对象,因此它不会生成实体键。

明白的是,为什么EF在读取重复的主键值时不会抛出exception。 现在,它在SQL查询结果中遇到其键值时,会静默返回同一个对象。 这导致许多人感到困惑到无穷无尽。

顺便说一下,避免此问题的常用方法是在Sql Server中使用ROW_NUMBER为视图生成临时唯一键值。 这对于您只读入一个上下文实例的只读数据就足够了。