53

I'm trying to update one value of a compound primary key from within the entity framework and I'm getting this error: "The property 'CustomerID' is part of the object's key information and cannot be modified. "

Here is my code:

Dim customer As Customer = (From c In db.Customer Where c.CustomerID = "xxx" AndAlso c.SiteKey = siteKey).FirstOrDefault
customer.CustomerID = "fasdfasdf"
db.SaveChanges()

It seems too simple. Is it true you can't update a primary key within the entity framework? I can't find any documentation on the topic. Thanks!

Paul Lemke
  • 5,494
  • 3
  • 47
  • 66
  • 9
    can I ask why you want to change the primary key, that is very very very bad practice. – Nathan W Sep 02 '09 at 13:46
  • 1
    Good question. We have anonymous information being tracked in the database by their anonymous customerid. When the user logs in i want to update the table and set that to their regular customerid. – Paul Lemke Sep 02 '09 at 13:49
  • 4
    Just me, I would have two tables one for anonymous users then when they login create a new record in the main table, but never ever modify the primary. – Nathan W Sep 02 '09 at 13:51
  • 2
    Eh, why dupe a table structure when it's identical information just with a different customerid? :) Programming style i guess... I'd still love to know why the entity framework doesn't allow updating of primary keys? – Paul Lemke Sep 02 '09 at 13:55
  • 4
    @lemkepf said _why the entity framework doesn't allow updating of primary keys?_ it might be that is can't/doesn't want to handle cascading the update to all FKs. this is a tricky task, and why most people consider it _BAD_ to update keys – KM. Sep 02 '09 at 14:08
  • 1
    I found this [post](http://stackoverflow.com/questions/7800130/update-part-of-primary-key-entity-framework-4-0) which helped me on this issue. If entity can't do it, sql will do it (using `ExecuteStoreCommand`) – BornToCode Dec 11 '12 at 16:04

7 Answers7

63

I have a Ph.D. in cs - in the area of Databases, so this answer will be a bit different than a programmers perspective. With all respect to Oliver Hanappi, a key can and occasionally does change if it is not a surrogate key. E.g. A natural key or a composit key. For example. It is possible to get your SSN changed in the US. But many programmers down through the years would consider this an unchangeable key and use it as such. It is much more common to change a composite primary key made up of foreign keys.

I'm dealing with a database that has a ternary relationship. Specifically three entities (with foreign keys being surrogate primary keys in their respective tables). However, to preserve the relationship between two entities while changing the third entity requires changing part of the intersection table (also called a pure join table on MSDN) primary key. This is a valid design and could only be improved by removing the ternary relationship intersection table and replacing it with two binary relationship tables (that may have their own surrogate keys). EF would handles this fine. This design change would make a (Many->many)->many or Parent1-Parent2 -> Child-grandchild model (if that's not clear read the example below). Entity framework would work fine with this as each relationship is really a one to many relationshiop. But its a crazy design from a DB perspective. Let me show you an example why.

Consider that Course, Classroom and Instructor are associated with one another in a class. Class could include: CourseID, ClassroomID, InstructorID as foreign keys and contain a composit primary key including all three. Although a clear, concise ternary model (3 way relationship) we could break it up into binary relationships. This would give two intersection tables. Adding surrogate keys would satisfy EF as follows:

Class(SurrogateKeyClass, InstructorID, CourseID)

ClassRoomUsed(SurrogateKeyClassroomUsed, SurrogateKeyClass, ClassRoomID)

The problem with this design is that we could have the same course and instructor associated multiple times, which the previous model avoids. To avoid this problem, you can add a constraint in the database for uniqueness of the two ID fields, but why would you want to do this when you are only dealing with surrogate keys to start with? However this solution would work as best as I can tell. This is not however a logic database design because of the unatural unique constraint required in the DB.

BUT, if you don't want to change your database or can't change your database, here is a second solution: Intersection/association tables are just that, links linking two entities or more together. If one changes, delete the association and recreate a new one that has the appropriate foreign keys (navigation properties). That means that you will not be allowed to require child entities in any of the relationships, but that is extremely common.

I would suggest that the Entity Framework (in the future) allow those of us who can design an elegant DB model to change parts of keys in intersection/association tables when we want!

Another Example for free:

Consider a Student, Course, Grade Association. Students are associated with a course via a grade. Usually this is a many to many association between Student and a Course with an additional field in the association table called grade (association tables have payload data like grade, intersection tables do not have a payload and are refered to in MSDN as pure join tables at lease in one place):

Student(StudentID, ....)

Course(CourseID, ...)

Taking(StudentID, CourseID, grade)

If someone makes a data entry error from a dropdown and puts a student in the wrong class, you like them to change it later by selecting the dropdown again and selecting a different course. In the background you will need to delete the EF object from the Taking table and recreate it without losing a grade if there is one. Simply changing the Foreign Key CourseID seems like a better alternative. Come up with your own association if this one seems contrived, but as a professor it was natural for me.

Conclusion: When you have a string of relationships, it may be better not to allow cascading and/or changing FK, but there exists resonable/logical scenarios where it is needed, even if not recommended as a best practice in general.

This problem may manifest itself with the following Exceptions depending on if you are changing the navigation property or the key property in the model respectively:

A referential integrity constraint violation occurred: A primary key property that is a part of referential integrity constraint cannot be changed when the dependent object is Unchanged unless it is being set to the association's principal object. The principal object must be tracked and not marked for deletion.

The property 'X' is part of the object's key information and cannot be modified.

xpda
  • 15,585
  • 8
  • 51
  • 82
Dr. A
  • 839
  • 1
  • 7
  • 10
  • 1
    I have exactly this situation and your comments are spot on. – xan Dec 31 '12 at 14:06
  • 1
    Very nice answer. I usually use surrogate PKs "for consistency" (and introduce other CKs as required), except when used as a join table where they always seem like a terrible kludge .. the example makes a good bit of sense. – user2246674 Jul 17 '13 at 22:36
23

You cannot update the primary key through entity framework, since entity framework would not know which database row to update.

However, if you really need to do it, you could write a stored procedure that updates the primary key, and then execute the stored procedure from entity framework.

Shiraz Bhaiji
  • 64,065
  • 34
  • 143
  • 252
  • 2
    -1 you should never need to do it. You database design is wrong if you do. – Nathan W Sep 03 '09 at 01:30
  • 10
    @Nathan, I agree with you that it should not be nessessary, we only use auto increment id's. However, the question was is it possible, and this is a way to do it. – Shiraz Bhaiji Sep 03 '09 at 06:30
  • 1
    Shiraz: This is the way to go. @Nathan: I don't see why updating natural keys is bad database design. See Dr. A'a answer. – Maksymilian Majer Jan 18 '12 at 14:07
  • 2
    Intersection tables do provide a valid use case. I have a situation where "Cases" in my system can be linked together in various ways. EG: one can be set as a duplicate of another. An intersection table with all FK's records the unique combination of CaseFrom, CaseTo and LinkType. Sometimes the specified duplicate changes. I would like to be able to update the row (much easier to audit) rather than delete / add. – xan Dec 31 '12 at 14:02
  • Downvote for "not know which database row to update". Entity Framework tracks original values. – NetMage Jul 14 '17 at 18:47
  • 2
    I have a table to control locations of items; each item has 4 fields to identify its *unique* location. So, logically, the 4 fields make up a PK. Changing location is desirable, however, so the PK needs to change. Of course, I could add a table with unique key to point at locations but that's silly. – Gary Huckabone Apr 05 '21 at 21:23
9

You can't and for good reason. See KM comments.

One thing I say you could do is have two tables one with anonymous data and one that stores the the real user data after they log in.

Or your could (not tested or ever done by me) is have this kind of table layout:

---Customers----
AutoNumber PK <- This links to all other tables in your database, and does NOT change.
CustomerID  <- This can change.
CustomerType <- Anonymous or logged in.  

And when they log in you change the CustomerType and CustomerID to what you need.

So your query could look like this:

Dim customer As Customer = (From c In db.Customer _
                            Where c.CustomerID = {Some temp ID} _
                            AndAlso c. CustomerType = "Anonymous").FirstOrDefault
// After user logs in.
customer.CustomerID = {Make a new user ID here}
customer.CustomerType = "LoggedIn" {or what ever}
db.SaveChanges()

Note that the autonumber primary key never changes. This is so that any tables that you have in a relationship with the Customers table still work and don't have to do cascading updates on the primary key (which is like stabbing yourself in the eye with a pencil).

Nathan W
  • 54,475
  • 27
  • 99
  • 146
  • 1
    How about when Entity Framework thinks something is a key, and I don't see that it's a key in the database. What do you do then?? – Dexter Jan 06 '11 at 20:25
  • 44
    I don't agree with this: "for good reason." I know it's bad practice some of the time, but there are exceptions. If I'm using a natural/multi-part key to store phone numbers, for instance, why should I be forced to create a surrogate key just to update the phone type? EF should stay out of my business and do what I tell it to. This is a bad limitation of the system. – Shea Daniels Mar 16 '11 at 22:30
  • 3
    "bad practice some of the time" It's bad practice all of the time. I have never seen a case where it is justified to be able to change the primary key. If you only have one table then no big deal but if you have linked tables and you started messing around with changing primary keys, it can get very messy. – Nathan W Mar 17 '11 at 02:26
  • I'm not sure exactly what you mean by linked tables. If you're talking about foreign keys, then I still disagree. If you're talking about using MS Access, then the fact that you're using access is the real problem. Here is an example: I am storing phone numbers for a person. Those phone numbers are not referenced anywhere else. To me, it makes sense to use a natural key consisting of person ID and phone type, since only one number is allowed per type. Say I made a mistake and need to change from Home phone to Mobile. Why shouldn't this be allowed? – Shea Daniels Mar 17 '11 at 14:42
  • Linked = Relationship that is what I meant. No I don't use access, killed that off long ago. Like I said if it's one table and no relationships that's fine once you have relationships it gets messy. The general rule I have always heard/read is don't make your keys intelligent (http://www.agiledata.org/essays/keys.html), just a plain number or GUID works fine. You can still have a generated key for display reason eg for a form, but this is not what is used to join tables. If you use a natural key and you make a mistake in your phone number the you have to handle cascading updates. – Nathan W Mar 17 '11 at 21:17
  • 4
    I'll give a you a real world example of the problem they can create, someone at my work decided it would be a good idea to create IDs for our road network using {Road Name}({Suburb})_{Segment Number} eg ACACIA ST (KLN)_50 now this is the primary key and linked to a lot of things, eg last year financial record, some valuation stuff etc and a heap of other tables , it is also a "smart key" because it contains business data. Now guess what happens ACACIA ST is wrong, say it's ACACI ST or what ever, now your ID is out of sync with the real road name and people think they should just change it... – Nathan W Mar 17 '11 at 21:27
  • 2
    this requires updates all back though the financial records because now the ID link is broken. If they had have used just a plain number and the road changed, they would just change the name of the road and leave the ID the same and everything would still be intact. This is the no 1 reason for me to never ever use smart keys made up of other bits of data, it gives you a lot of problem that are just not worth it. – Nathan W Mar 17 '11 at 21:30
  • Nathan W if there database was designed to cascade the update of the foreign key enverything would stay in synch! – markmnl Aug 10 '12 at 01:55
  • 1
    in my experience older programmers always consider bad becuase they didnt have cascading updates on a key in their day – markmnl Aug 10 '12 at 01:55
  • 1
    available since 2000: http://msdn.microsoft.com/en-us/library/aa933119(v=sql.80).aspx – markmnl Aug 10 '12 at 02:04
  • 2
    @Fëanor who said the other data that uses the ID is stored in a database? Not everything is in the one system so cascading updates doesn't help. – Nathan W Aug 12 '12 at 23:24
  • So you agree now unless data is outside the database it is ok? – markmnl Aug 16 '12 at 03:02
  • 2
    The question asked is "Update primary key value using entity framework". The question is simple and straight forward, yet you suggest an approach that does not answer the question (Albeit it is the recommended way). What if you are working with a database where you absolutely cannot make any changes to the schema but you still need to update the PK fields? – TtT23 Feb 07 '17 at 19:22
  • @NathanW Yeah, I KNOW the problem they can create. But the fact is somebody _did_ do something almost identical to your example and now I have a system where I am going to have to change the primary keys when I delete a record. And EF getting in the way. – Auspex Mar 09 '18 at 16:43
0

If there could be only one instance of the database context at any time then modifying the pk would not be such a problem. But each context instance maintains its own cache and can be caching the record that you want to modify.

EF interactions with the database use the pk (from the context cache) to identify the record(s) that they are querying. If a context object could update the key in persistence, the information that other context objects rely upon to identity that record is immediately and permanently wrong.

In short, if you update the primary key you have invalidated the cache in potentially all other instances of the context, and that would break EF fundamentally. This is one of the bigger reasons why it's a bad idea to update a pk.

Tom
  • 336
  • 2
  • 9
0

You need to delete the old entity and insert it again with a modified ID. The easiest method is to JSON stringify the object to create a clone.

var cloned_account = DeserializeObject<account>(SerializeObject(existing_account));
cloned_account.user_id = 1;

db.account.Remove(existing_account);
db.account.Add(cloned_account);
George
  • 131
  • 1
  • 5
  • Comments on other answers mentioned this being bad design. Yes you shouldn't do this all the time as it carries risk, but in my specific case I needed to change a foreign primary key to move an account between users. Ideally I would "go back" and change the entire database structure to use a different primary key, but that's not always possible. – George Aug 12 '21 at 23:48
0

I would like to suggest that instead of updating primary key, its better to insert another row with new primary key and delete the old one. However you need to be aware to change all the child entities to refer to the new primary key pair

Fitri Halim
  • 584
  • 4
  • 11
  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/30137433) –  Oct 21 '21 at 10:03
-5

You cannot update a primary key, but that is not a limitation of entity framework, but a very fundamental rule of database development. A primary key is assigned once to a row in a table and makes this row unique.
Maybe you can update the key in some ways, but this violates definitely the definition of a primary key.

So, just don't do it, there are other ways to accomplish what you are trying to do.

agf
  • 171,228
  • 44
  • 289
  • 238
Oliver Hanappi
  • 12,046
  • 7
  • 51
  • 68
  • 2
    it is an outdated rule of thumb and certainly not fundemental. since cascading updates on a col everything stays in synch so unless you have data outside your database (which is bad) there is no problem – markmnl Aug 10 '12 at 01:58