C#中EF查询生成的两个Color列表为何相互影响?如何解决?
我有一个名为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; } }
通过EF上下文查询生成两个Color列表,记录可能重叠或不同:
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")}
实际错误输出:
ViewBag.Colors1.Items = {(1,"bl || blue || blue"),(2,"gr || green || green"),(3,"bk || black")}
ViewBag.Colors2.Items = {(1,"bl || blue || blue"),(2,"gr || green || green"),(3,"wt || white")}
修改colors2时会影响colors1的内容,请问如何解决?
Entity Framework的上下文默认会跟踪查询到的实体,当两次查询返回同一个数据库记录(即Id相同的Color对象)时,上下文会返回同一个内存引用的对象实例。也就是说,colors1和colors2中Id为1、2的实体是同一个对象,修改其中一个列表里的实体属性,另一个列表里的对应实体也会跟着变化,因为它们指向的是内存中的同一个对象。
在查询末尾添加AsNoTracking()方法,关闭EF对查询结果的跟踪。这样每次查询都会返回全新的对象实例,两个列表中的实体不再共享内存引用,修改其中一个不会影响另一个。
修改后的查询代码:
List<Color> colors1 = _context.Colors.Where(c => c.MaterialStatus == true).AsNoTracking().ToList(); List<Color> colors2 = _context.Colors.Where(c => c.GoodsStatus == true).AsNoTracking().ToList();
执行上述修改后,就能得到预期的输出结果。
内容的提问来源于stack exchange,提问作者NedaM

