为什么两个具有不同名称和相同类型的列表作为 SQL 查询的输出,对彼此的 C# 有影响?

Why two lists with different names and same types that are outputs of a SQL query, have effect on each other C#?

提问人:NedaM 提问时间:10/10/2023 最后编辑:NedaM 更新时间:10/10/2023 访问量:65

问:

我有一个名为 Color 的数据库表。

public class Color
{
    public int Id { get; set; }
    public string ColorCode { get; set; }
    public string ColorName { get; set; }
    public bool MaterialStatus { get; set; }
    public bool GoodsStatus { get; set; }
}

我定义了两个具有相同或不同记录的颜色列表。

List<Color> colors1 = _context.Colors.Where(c => c.MaterialStatus == true).ToList();
List<Color> colors2 = _context.Colors.Where(c => c.GoodsStatus == true).ToList();

例如,输出为:

colors1 ={(1,bl,blue,true,true) , (2,gr,green,true,true) , (3,bk,black,true,false)} colors2 ={(1,bl,blue,true,true) , (2,gr,green,true,true) , (3,wt,white,false,true)}

然后我对这些列表进行了一些更改,如下所示:

colors1.ForEach(c => c.ColorCode = c.ColorCode + " || " + c.ColorName);
ViewBag.Colors1 = new SelectList(colors1, "Id", "ColorCode");

colors2.ForEach(c => c.ColorCode = c.ColorCode + " || " + c.ColorName);
ViewBag.Colors2 = new SelectList(colors2, "Id", "ColorCode");

所需的输出必须是:

ViewBag.Colors1.Items = {(1,“bl || blue”),(2,“gr || green”),(3,“bk || black”)}

ViewBag.Colors2.Items = {(1,“bl || blue”),(2,“gr || green”),(3,“wt || white”)}

问题就在那里。更改 Colors2 会对 Colors1 产生影响,输出将出错,如下所示:

ViewBag.Colors1.Items = {(1,“bl || blue || blue”),(2,“gr || green || green”),(3,“bk || black”)}

ViewBag.Colors1.Items = {(1,“bl || blue || blue”),(2,“gr || green || green”),(3,“wt || white”)}

我不明白为什么会这样。如何防止此问题并获得正确的输出?

正确答案:

我通过在查询末尾添加来更改我的代码,它起作用了!!!AsNoTracking()

List<Color> colors1 = _context.Colors.Where(c => c.MaterialStatus == true).AsNoTracking().ToList();
List<Color> colors2 = _context.Colors.Where(c => c.GoodsStatus == true).AsNoTracking().ToList();
C# 列表 LINQ 实体框架核心 跟踪

评论

4赞 Fildor 10/10/2023
您正在操作实际的数据库实体。不要。投影到您专门为显示目的而创建的类型。正在缓存实体。这就是为什么您从两个查询(它们重叠的地方)获取相同的实例的原因。

答:

4赞 Marc Gravell 10/10/2023 #1

如果你从 ORM(EF 等)获取它们:请注意,ORM 倾向于(默认情况下)使用身份缓存,因此,如果它们在同一数据上下文中看到相同的逻辑行(相同的表和主键)两次,它们每次都会给你相同的对象实例。这是为了保持一致性。

归根结底,您不应该更改跟踪的 ORM 实体,除非您打算 a:看到该更改在任何地方反映,并且 b:将该更改提交到数据库。如果您想要一些瞬态的东西:将实体投影到您自己的非跟踪类型中。