Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I update a foreign key efficiently in LINQ to SQL/SQLMetal?

I ran into an issue trying to update a foreign key field:

record.ForeignId = newId;

It bombs with "Operation is not valid due to the current state of the object" due to SQLMetal code that throws System.Data.Linq.ForeignKeyReferenceAlreadyHasValueException().

I was not the first to hit this issue:

LinqToSQL Error : Operation is not valid due to the current state of the object and http://social.msdn.microsoft.com/forums/en-US/linqtosql/thread/f9c4a01a-195a-4f2b-a1cb-e2fa06e28b25/ discuss it, amongst others.

Their solution is this:

record.Foreign = Database.Foreigns.Single(c => c.Id == newId);

That, of course causes a DB lookup on Foreign just to get an object back that has the Id I already know! So, how do I accomplish this update without the pointless query (or queries if I have lots of these FKs)?

like image 579
Scott Stafford Avatar asked Sep 03 '10 15:09

Scott Stafford


People also ask

How do you update a record in LINQ?

To update a row in the databaseQuery the database for the row to be updated. Make desired changes to member values in the resulting LINQ to SQL object. Submit the changes to the database.

Is LINQ to SQL deprecated?

LINQ to SQL was the first object-relational mapping technology released by Microsoft. It works well in basic scenarios and continues to be supported in Visual Studio, but it's no longer under active development.

Does LINQ optimize?

Does LINQ do any optimization by sorting/converting data structures? Yes. There are all sorts of optimizations that take place throughout various LINQ methods.

What is the key function of the LINQ to SQL classes?

LINQ to SQL supports stored procedures and user-defined functions. In LINQ to SQL, you map these database-defined abstractions to client objects so that you can access them in a strongly typed manner from client code.


2 Answers

You could new up an instance of the parent (with the correct Id), Attach it to the datacontext as the existing record state, then assign the Parent property of your child object.

Here's some code:

int theId = 5;
Parent p = new Parent() { Id = theId};
dc.Parents.Attach(p);
child.Parent = p;
like image 196
Amy B Avatar answered Oct 22 '22 10:10

Amy B


It doesn't solve the issue, but one way to partially get around the extra load is to check to see if the existing value is different than the new value. If it is different, you'll incur the query. Something like --

if(obj.PropertyID != newValue){
  obj.Property = PropertyClass.Load(newValue)
}
like image 32
InbetweenWeekends Avatar answered Oct 22 '22 09:10

InbetweenWeekends