简体   繁体   中英

Avoiding object saving in LINQ

For my LINQ object Foo, I want to have a "before-and-after" state bracketing my object mutation (coming from an ASP.NET MVC UpdateModel() call as it happens). My idea was to copy the pre-mutation properties from the attached instance into a new unattached instance. Then I'd be able to make the updates in the attached instance and compare their values versus those in the unattached instance. Like so:

Foo real = context.Foos.First(aFoo => aFoo.ID == id)
Foo old = new Foo();
old.Bar = real.Bar;
old.Baz = real.Baz;
SomeSortOfUpdate(real);
if ( !real.Bar.Equals(old.Bar) || real.Baz.Equals(old.Baz) ) {
   LogChanges(old, real);
}
context.SubmitChanges();

Here's the problem: the object referenced by "Foo old" is getting saved (inserted) during context.SubmitChanges() . I traced this back to the assignment of properties that were LINQ-to-SQL associations.

So, for example, if Baz was a table-backed L2S-generated type, including old.Baz = real.Baz would cause a SQL insert for old in addition to any SQL update for real . Removing it (yet keeping old.Bar ) makes things work as I expect.

I'm guessing that this is because the Foo.Baz assignment makes a link between Foo and Baz in the saveable object graph. Since real is getting saved, LINQ also walks all of the associated objects and looks for changes. real.Baz isn't itself changed, but it has a new association to old , which isn't yet saved and so gets caught up in the SubmitChanges call.

Is there any way I can prevent objects in the graph from being saved?

Your analysis is correct. Your assignments are establishing links.

You can modify the generated code to not do this (or write your own). But this means you have to live without auto-generated entity classes. I personally consider this to be unacceptable.

Why don't you serialize the pre-image object into a dictionary? Or copy its property values into a custom DTO class?

From your code I can tell that you want the old values to do change logging. You can do that using

DataContext.GetTable<T>().GetModifiedMembers(entity)

I wonder what this would do

 var old = (Foo)real;

I'm wondering if the instance itself is creating the connection

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM