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

本文关键字:框架 实体 映射 数据 错误 标识 唯一 | 更新日期: 2023-09-27 18:29:59

在不讨论"为什么"的情况下,只需了解继承中的这一点以及我必须使用的内容:)

我有一个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行映射为相同的行。上面所有的"John"名字都变成了"Jane"

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

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

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

因此EF不能简单地实现具有重复主键值的对象。这将损害其追踪机制。

看来,至少在EF6中,AsNoTracking()可以用作变通方案。AsNoTracking告诉EF只实现对象而不跟踪它们,这样它就不会生成实体键。

我不明白的是,为什么EF在读取重复主键值时不抛出异常。现在,当它在SQL查询结果中遇到其键值时,它会静默地多次返回相同的对象。这让许多人感到困惑。

顺便说一句,避免此问题的常见方法是在SqlServer中使用ROW_NUMBER为视图生成临时唯一键值。这对于只读数据来说已经足够好了,只需在一个上下文实例中读取一次即可。