0

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?

rwkiii
  • 5,716
  • 18
  • 65
  • 114

1 Answers1

1

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 }
    }
}
Community
  • 1
  • 1
Vsevolod Goloviznin
  • 12,074
  • 1
  • 49
  • 50
  • Very simple solution. I did not realize I was passing a reference to the vars. This makes sense... I'm sure your answer is correct, but I want to change my code and see that this solves the problem. I will mark your answer after I make sure this is the cause of my problem. Thank you! – rwkiii Dec 14 '14 at 19:49
  • what if I need to create an individual `MyVal`? I tried `MyVal myval = new MyVal(m)` but I get an error saying MyVal does not contain a constructor that takes 1 argument. Do I need to modify the MyVal class or am I trying to create `myval` incorrectly? – rwkiii Dec 14 '14 at 19:55