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

C# 当标识列不唯一时,实体框架映射数据错误,c#,entity-framework,C#,Entity Framework,不必问“为什么”,只需理解这一点以及我必须处理的问题:) 我有一个映射到视图的EF6 edmx。上面没有标识列,因此为了让EF映射实体,选择了第一个NOTNULL列作为PK。最初的想法是它是只读的,不会进行更新或删除。没有筛选(ODATA位于此项之上),唯一使用此项的方法是从实体中选择top N* 视图中有4条记录 TypeCode | Contact | UserID | LocaleID | EntityName ---------------------------------------

不必问“为什么”,只需理解这一点以及我必须处理的问题:)

我有一个映射到视图的EF6 edmx。上面没有标识列,因此为了让EF映射实体,选择了第一个NOTNULL列作为PK。最初的想法是它是只读的,不会进行更新或删除。没有筛选(ODATA位于此项之上),唯一使用此项的方法是从实体中选择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
,所以它不知道如何操作。但是,当它只是从数据库中读取结果时,为什么要使用键列呢?我原以为它只对更新和删除重要,如果按实体框架查询数据,默认行为是每个具体化的实体都由其唯一的键跟踪。唯一键由您告诉EF用作键的任何属性组成,或者,它被推断为键属性(
TypeCode
)。每当重复的实体键尝试进入更改跟踪器时,就会抛出一个错误,告知对象已被跟踪

因此EF无法具体化具有重复主键值的对象。这将损害其追踪机制

看来,至少在EF6中,可以作为一种变通方法
AsNoTracking
告诉EF只具体化对象而不跟踪它们,因此它不会生成实体键

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


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

Joe,这有关系吗?我们知道它是这样工作的,您必须接受它。@IvanStoev知道吗?它实际上使用了定义为selects中的键的列吗。没有文档或解释链接,我从这篇文章中学到了,但后来在许多其他地方也发现了类似的内容。你看过SQL Profiler的内容了吗?幕后发生了什么疑问?另外,将所有列放在一起作为主键可以解决这个问题吗?我已经将sql生成的返回数据更正为EF。EF本身正在做一些奇怪的事情。我不能使其他列成为键的一部分,因为它们可以为null。我上面的问题是一个非常简化的版本。最疯狂的是那四排。表中有14K条记录,所有记录都具有相同的TypeCode值,并且这些记录不显示相同的行为。我唯一能想到的是这4条记录在其他3列中共享数据。我认为在具体化记录时,EF可能不仅仅是一个“简单”的身份映射模式。不管是哪种方式,我都会尝试使用
AsNoTracking
,看看有什么好奇怪的,你知道在EF代码中这是在哪里完成的吗?我正在他们的Github附近搜寻,但是没有任何用处,我经常翻阅EF代码,但是如果我能一下子就知道这一点,我会成为一名学者。但是知道了这一点你会得到什么呢?事实上,要改变这种行为(如果你愿意的话)是不可能的,因为它是EF跟踪机制的基础。因为我想逐步了解它,看看到底发生了什么。为了学习而学习?就像四排一样。您确定EF仅将
TypeCode
推断为主键吗?你对这种行为的描述让我觉得它还需要另外三个。