Search code examples
c#listlinqentity-framework-coretracking

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


I have a DB table with name of 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; }
}

I defined two lists of color that have same or different records.

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

For example output is:

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

then I did some changes on these list like below:

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");

desired output must be:

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

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

problem is there. changing on colors2 have effects on colors1 and output will be wrong, like below:

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

I don't realize why this happened. How can I prevent this problem and get correct output?

correct answer:

I changed my code by adding AsNoTracking() at the end of query, and it worked!!!!

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

Solution

  • If you're fetching those from an ORM (EF, etc): note that ORMs tend to use (by default) an identity cache, so that if they see the same logical row (same table and primary key) twice in the same data-context, they give you the same object instance each time. This is for consistency.

    Ultimately, you shouldn't change tracked ORM entities unless you intend to a: see that change reflected everywhere, and b: commit that change to the database. If you want something transient: project the entity into your own non-tracked type.