rwkiii
rwkiii

Reputation: 5846

How to stop tracking/mapping between variables in EF

I have an EF Code First table that contains data I do not ever want to change, but I want to retrieve the data to a couple of variables that are independent of each other. The problem is that making a change to either variable changes the values of the other one.

For example, the EF Code First context is defined:

public class MyVal {
    public int id { get; set; }
    public double SomeVal { get; set; }
}

After populating the table with data:

context.MyVals.AddOrUpdate(new MyVal { SomeVal = 1 });
context.MyVals.AddOrUpdate(new MyVal { SomeVal = 2 });
context.MyVals.AddOrUpdate(new MyVal { SomeVal = 3 });

Next, I perform a query:

List<MyVal> myvals = _context.MyVals.AsNoTracking().Where(d => d.SomeVal >= 0).Select(m => m).ToList();

The above query returns the expected data. As you can see, I've specified AsNoTracking(). Next I want to create another var that I will modify:

List<MyVal> myvals1 = myvals;

And now I want to modify myvals1 WITHOUT effecting any values in myvals:

foreach (MyVal m in myvals1) {
    m.SomeVal = m.SomeVal * 2;
}

myvals1 will now contain 3 records with these values:

2
4
6

The problem is that myvals also gets changed to:

2
4
6

Since I used AsNoTracking() when I queried the context, what else do I need to do to make these variables independent of each other? Why are these variables seemingly treated as the same?

Upvotes: 0

Views: 436

Answers (1)

Vsevolod Goloviznin
Vsevolod Goloviznin

Reputation: 12324

The thing is that you are not creating a new object by simply assigning to a variable, as object int c# are passed by reference, not by a value. So when you are assigning myvals to myvals1 you simply pass a reference to the same object. So you need to create a new List and work with it:

List<MyVal> myvals1 = new List<MyVal>(myvals);

If you need to create an object of MyVal from another object there are multiple solutions like implementing IClonable interface, creating a Clone method (the simple implementation won't work for nested complex objects, to do this check this question: Deep cloning objects), using an AutoMapper library.

Here's an example of creating a Clone method:

public class MyVal 
{
    public int id { get; set; }
    public double SomeVal { get; set; }

    public MyVal Clone(MyVal obj)
    {
        return new MyVal {id = obj.id, SomeVal = obj.SomeVal }
    }
}

Upvotes: 1

Related Questions