Reputation:
Without getting into the "why", just understand this in inherited and what I have to work with :)
I have an EF6 edmx mapped to a view. There is no identifying column on it, so in order for EF to map the entity, the first not-null column was selected as the PK. The original thought behind this was it is read only no updates or deletes would be done. There is no filtering (ODATA sits on top of this), and the only - and I mean only - way this is used is select top N *
from the entity.
There are 4 records in the view.
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
The problem I am seeing is that EF is mapping all 4 rows the same. All "John" names above become "Jane"
OK, putting aside the design decision, and the fact there is no identifying record on the view, why is EF mapping the last two rows wrong? My initial thought is that since the "PK" is set as TypeCode
It doesn't know how to do it. But why would it be using the key column when just reading results from the database? I would have thought it only mattered for updates and deletes
Upvotes: 2
Views: 2443
Reputation: 109079
If you query data by Entity Framework, the default behavior is that each materialized entity is tracked by its unique key. The unique key consists of any properties you told EF to use as key, or, alternatively, it inferred as key properties (TypeCode
in your case). Whenever a duplicate entity key tries to enter the change tracker, an error is thrown telling that the object is already being tracked.
So EF simply can't materialize objects having duplicate primary key values. It would compromise its tracking mechanism.
It appears that, at least in EF6, AsNoTracking()
can be used as a work-around. AsNoTracking
tells EF to just materialize objects without tracking them, so it doesn't generate entity keys.
What I don't understand is why EF doesn't throw an exception whenever it reads duplicate primary key values. Now it silently returns the same object as many times as it encounters its key value in the SQL query result. This has caused many many people to get confused to no end.
By the way, a common way to avoid this issue is by generating temporary unique key values to the view by using ROW_NUMBER
in Sql Server. That's good enough for read-only data that you read once into one context instance.
Upvotes: 6