如何停止EF中变量之间的跟踪/映射

时间:2014-12-14 19:42:13

标签: c# entity-framework

我有一个EF Code First表,其中包含我不想改变的数据,但我想将数据检索到几个彼此独立的变量。问题是对任一变量进行更改会更改另一个变量的值。

例如,定义了EF Code First上下文:

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

用数据填充表后:

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

接下来,我执行查询:

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

上述查询返回预期数据。如您所见,我已经指定了AsNoTracking()。接下来我想创建另一个我将修改的var:

List<MyVal> myvals1 = myvals;

现在我想修改myvals1而不影响myvals中的任何值:

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

myvals1现在将包含3条包含以下值的记录:

2
4
6

问题是myvals也变为:

2
4
6

由于我在查询上下文时使用了AsNoTracking(),我还需要做些什么来使这些变量相互独立?为什么这些变量看似被视为相同?

1 个答案:

答案 0 :(得分:1)

问题在于,您不是通过简单地分配给变量来创建新对象,因为对象int c#是通过引用传递的,而不是通过值传递的。因此,当您将myvals分配给myvals1时,您只需将引用传递给同一个对象。因此,您需要创建一个新的List并使用它:

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

如果你需要从另一个对象创建MyVal的对象,有多个解决方案,比如实现IClonable接口,创建一个Clone方法(简单的实现不会起作用)对于嵌套的复杂对象,要执行此操作,请使用AutoMapper库检查此问题:Deep cloning objects)。

以下是创建Clone方法的示例:

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 }
    }
}