Why do I get odd results from mysql EF query? [duplicate] - c#

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

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.

Related

Why SQL server view is not good to work with Entity Framework

i read these articles
http://a4academics.com/interview-questions/52-dot-net-interview-questions/973-entity-framework?showall=&start=2
they said
Below are the points we can consider increasing the performance –
Disable the Change Tracking if it’s not required.
Use the compiled
query whenever required.
Avoid using Views
Fetch the required data
from database.
1) what they try to mean avoid using views.
we can have views in db and that we can refer by edmx. so what would be the problem if we call view by EF instead of table ?
i like to know what happen when we call view by EF.
Thanks
Really the only problem with views is that they don't always contain unique candidate primary keys.
A view can contain rows like
ID1 ID2 SomeColumn
==================
1 4 A
1 5 A
1 5 B
where both ID columns originate from primary key table columns.
When imported into an EDMX, EF will infer a primary key and may conclude that { ID1, ID2 } is a good candidate. As you see, it isn't. In this case it should also include SomeColumn, but in other cases there may not even be a unique combination of view fields!
In Entity Framework 6 and earlier that caused EF to materialize identical entities like
1 4 A
1 5 A
1 5 A (!)
As you see, the third row is duplicated.
This has caused great confusion among developers and lots of Stack Overflow questions. It's just that when the view contains a proper unique candidate key, which is mapped as primary key in the EF model, it's perfectly OK to use views for read-only data in EF queries.
This confusing issue won't be fixed in EF6 any more, but Entity Framework core (as of v2.1) has added support for reading unidentifiable view data. A view can be read into any type and reading the view will simply return the view rows without duplications caused by non-unique keys: there are no keys.
The type can be added to the model by:
modelBuilder.Query<MyViewDto>().ToView("MyView");
...and used in a LINQ query like so:
db.Query<MyViewDto>().Where(x => x.ID1 == 1)
This will be translated into a SQL query with a WHERE clause.

Update operation violates unique constraint

I need to implement a "shift by year" operation in my Entity Framework application.
To simplify things, let's suppose I have an entity / table that has a foreign key FK to some other table and a YEAR (int, int). Users may shift the entity years to the future, so I need to copy data from 2017 to 2018 and so forth.
There's a restriction in the database that says that the pair (FK, YEAR) must be unique.
When I perform the "shift" in memory and send the changes to the database with SaveChanges I receive an error from the database that I'm violating the unique constraint. I suppose that it is trying to perform the update row by row, therefore the violation.
If I sort the collection by year descending (so no duplicates happen if the rows are sent one by one) the same error happens.
My workaround is to delete the old data and insert new data with the new years, but I think there might be a cleaner solution...
I solved the issue by inverting the order and saving item by item after modifying. It's not very clean to run so many SaveChanges but the overall process is rather complex and it's using transactions, so it's not a big deal.
I had to make some more changes because users can shift years to the past or to the future, in which case I must / mustn't reverse the order, but to simplify this very issue let's say that it's solved if I reverse the order and save item by item.

How to have more than 1 many-to-many relationship

My problem is simple but I can't seem to get EF to understand my database schema (Oracle).
Problem
I want to model more than 1 M-M relationship see diagram below:
As you can see I have a book and a journal - and I want to store a URI against both of these, by way of using a linking table (junction table, intersection table, you get it!). In this case it happens to be "www.google.com" that I want to store against Journal 16 and Book 75, they would be stored in the linking table in the follwoing format marked out in blue. For completeness I have added a green example for link with an ID of 5.
So you can see how the data knits together, I think you'll agree it's nothing too crazy.
Anyway, when I try and update EF model, it complains (in Visual Studio) with an error along the lines of.
Problem in mapping fragments starting at line 210:Foreign key constraint 'REF_URI_JOURNAL_FK1' from table REF_URI (REF_ID) to table JOURNALs (REF_ID): The columns of table REF_URI are mapped to AssociationSet BOOK_URISet's End BOOKs but the key columns of table JOURNALs are not mapped to the keys of the EntitySet BOOKs corresponding to this End.
Yeh - not really getting that error message!
I can get EF to work with 1 M-M relationship, e.g.
and it all works "hunky dory", but when I added a second M-M relationship it fell over with that error message above e.g.
Anyone know how I can get round this?
For two many-to-many relationships your need two linking tables (junction tables, intersection tables) REFBOOK_URI and REFJOURNAL_URI. I think that is what the exception is saying in a cryptic fashion. If you only had one table it would mean that if Journal 123 links to URI 789 then also Book 123 must also link to URI 789 because the REF_ID column in the link table would be a non-nullable foreign key to both the Journal and the Book table.

C# Entity Framework: Update Query Does not work

I have this simple code : (update value)
I'm trying to update column "c"
using (MaxEntities ctx = new MaxEntities())
{
aa orders = (from order in ctx.aa
select order).First();
orders.c = 22;
ctx.SaveChanges();
}
this is the table :
CREATE TABLE [dbo].[aa](
[a] [int] NULL,
[b] [int] NOT NULL,
[c] [int] NOT NULL
) ON [PRIMARY]
and values inside :
but i get an exception :
The property 'c' is part of the object's key information and cannot be modified.
I'm new to EF.
any help will be much appreciated.
The property 'c' is part of the object's key information and cannot be modified.
That's why you can't edit it. Maybe you need to add id column as a key with identity specified
As explained in another answer EF must uniquely identify every entity. If you don't have PK in the database, EF will infer some key. Key is considered as fixed so if EF inferred c as part of the key (and it did it because it uses all non-nullable non-binary columns) you cannot change its value. Moreover EF takes all tables without primary key as readonly so even if you remove c from the key in the designer and modify c value you will get another exception when you execute SaveChanges.
The reason for the second exception is in the way how EF describes model and the database. When EF inferred key, it did it only for description of your entities and for context's internal needs but not for description of the database. When EF tries to save changes it builds UPDATE statement from database description and without information about real database PK columns it will not be able to identify correct record for update (every update in EF can affect only single record - EF checks ROWCOUNT). This can be solved by cheating EF and updating its database description = by describing some column in the table description as primary key. This leads to multiple problems:
You must have some unique column in the database otherwise this method will not work.
You must edit EDMX manually (as XML) to add this change
You must not use default MS EDMX designer for updating your model from database because it will delete your change
Simple advice: Either use database tables with primary keys or don't use Entity framework.
Primary key missing here. Add primary key in table and it work.
I believe if there's no PK at all, EF uses all of the fields/columns as part of the key info.Here's a nice explanation: by #SteveWilkes of why. But what do your entities look like? The other possibility is that it doesn't have a property because the association is inside a different entity, if this is a foreign key.
EDIT
This got me thinking. There are just going to be situations where you have to work with legacy tables having no PK, even if you would never create such a thing. What about views? EF is a mapper - it has to uniquely identify that record so it infers and defines this key. Yes, you could use stored procedures, but could you also hack the XML and remove the keys from the table definition?
AND EDIT AGAIN
After posting this, I see #Ladislav Mrnka already said a similar idea (cheating EF and updating its database description), so it has been done (WARNING: Consume at your own risk - never tried). Quick google got me this blog with clear instructions:
Close the model designer in Visual Studio if it is still open and re-open the .edmx file in an XML editor
Find the edmx:StorageModels -> Schema -> Entity Container -> EntitySet element that refers to the table in question
On the EntitySet element, rename the store:Schema attribute to Schema
Remove the store:Name attribute altogether
Remove the opening and closing DefiningQuery tags and everything in between them
Save and close the .edmx file
But really, who doesn't like a PK? Can you not add an id?

"A cycle was detected in the set of changes" When trying to add a circularly linked list to the database

I'm using a 'in database' circularly linked list (cll). I'm inserting the database entries forming these cll's using Linq to Sql.
They have the general form:
id uuid | nextId uuid | current bit
If i try to do a SubmitChanges with a few objects forming a complete cll, i get the error "A cycle was detected in the set of changes".
I can circumvent this by making the linked list 'circular' in a separate SubmitChanges, but this has two down sides: I'm losing my capability to do this in one transaction. For a small period the data in my database isn't correct.
Is there a way to fix this behaviour?
The database needs to enforce its contraints, and I imagine you have a foreign key constraint between nextId and Id. If this chain of relations leads back to the start (as you have found) the database will not allow it.
I suspect your choices are:
Remove the foreign key constraint.
Store in the DB as a linked list, and only join the head with the tail in your code.
Even your second option won't work, as the DB won't allow you to add this last reference.

Categories