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

本文关键字:变量 EF 映射 停止跟踪 | 更新日期: 2023-09-27 18:34:15

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

例如,定义了 EF 代码优先上下文:

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((。接下来,我想创建另一个我将修改的变量:

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((,我还需要做什么才能使这些变量彼此独立?为什么这些变量似乎被视为相同?

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

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

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

如果您需要从另一个对象创建MyVal对象,有多种解决方案,例如实现IClonable接口,创建Clone方法(简单的实现不适用于嵌套的复杂对象,为此请检查这个问题:深度克隆对象(,使用AutoMapper库。

下面是创建 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 }
    }
}