当标识列不唯一时,实体框架会错误地映射数据

2 c# entity-framework

没有进入"为什么",只需了解继承和我必须使用的:)

我有一个映射到视图的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
Run Code Online (Sandbox Code Playgroud)

我看到的问题是EF将所有4行映射相同.以上所有"约翰"的名字都变成了"简"

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

Ger*_*old 6

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

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

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

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

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