Mike Jones
Mike Jones

Reputation: 1006

Updating objects in LINQ

I am trying to do an update in Linq.

public myFunc(MyItem newItem)
{
  using(var db = new myDataContext())
  {
     var item = (from o in db.myTable where o.id == myId select o).First();
     item = newItem;
     db.SubmitAllChanges();
  }
}

This doesn't update the object, I guess item = newItem changes item to refer to the other. If I change the individual fields (item.Name = newItem.Name etc.) te change is reflected, however I don't want to spread the contents of the MyItem class into multiple places to reduce maintainability. Is there some way to make the item=newItem copy on a field by field basis?

Also MyItem has a relationship to another table, and I want to update the subordinate items from newItem into item too. (FWIW, there are no adds or deletes, just updates.) Is there a standardized process for doing this?

Thanks for you help.

Upvotes: 1

Views: 214

Answers (5)

eglasius
eglasius

Reputation: 36037

An alternative option would be to use AutoMapper to automatically copy the values for you.

Above said, in many cases a simple method in a partial class would do just well (like in Jon Skeet answer).

Upvotes: 0

Dan Abramov
Dan Abramov

Reputation: 268255

I think you should gain some understanding of basic concepts of C# variables and references first.

Types in C# are divided into two groups: reference types and value types. They are different in many aspects, and copying and comparing is one of these aspects.

Value types include simple types like int (watch out: string is not a value type though you might think so), enumerations and structures. They get copied when you reassign values to different variables, pass them as parameters etc.

By saying

int x = 5;
int y = 7;
x = y;

You assign the value of y to x, which results in x being equal to 7.
However, if you change y further, x won't get updated:

int x = 5;
int y = 7;
x = y; // 7
y = 10; // x is still 7

On the contrary, reference types don't get copied on assignment. It's only references that get copied.

MyItem john = new Customer("John");
MyItem jack = new Customer("Jack");
jack = john; // now both references point to the same Customer

In this code snippet we forgot about Customer called "Jack" and both jack and john now point to the same object with name "John".

Therefore, by saying

item = newItem;

you only make item point to the object referenced by newItem at that moment (or null if it was empty).

You might want to define an Assign method in your class that performs the routine of assignment:

public void Assign(MyItem that)
{
    this.Name = that.Name;
    this.City = that.City;

    // etc
}

At some point, you might also want to write an extension method that uses reflection to assign all public properties—but that's a good topic for a different question (which most likely has already been asked and answered several times).

Upvotes: 2

Tim Mahy
Tim Mahy

Reputation: 1319

give it the same key and do an attach followed by a submitchanges....

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1500525

Well, MyItem should be a partial class - so you could add a CopyPropertiesFrom method to MyItem, and then write

item.CopyPropertiesFrom(newItem);

instead of your current assignment.

By the way, you might want to consider using this instead of your current query:

var item = db.myTable.First(o => o.id == myId);

Just makes things a bit simpler than a query expression in this case :)

Upvotes: 6

Justin Niessner
Justin Niessner

Reputation: 245429

You can't just assign newItem to item. When you assign newItem to item, it simply points item to a new location in memory...it doesn't actually update anything on the entity.

You need to go through and assign each property individually:

using(var db = new myDataContext())
{
    var item = db.myTable.First(o => o.id == myId);
    item.Prop1 = newItem.Prop1;
    item.Prop2 = newItem.Prop2;
    // etc
}

A better option would be to extend the partial class (as mentioned by Jon Skeet) from the Entity Model and make this a method (so you can re-use the code).

Upvotes: 4

Related Questions