2

I have two objects which are having value from same Query

i.e. (this is not c# code and is just pseudocode)

Class Obj = DbContext.Kid(K => K.Id == 2).FirstOrDefault();

Class Obj1 = DbContext.Kid(K => K.Id == 2).FirstOrDefault();

Id = 2 having Status = 1

Now if I set

Obj.Status = 2;

in C# code

Then Obj1 too changing its status from 1 to 2

Why this is so?

HariHaran
  • 3,642
  • 2
  • 16
  • 33
Gulfam
  • 558
  • 6
  • 27
  • 3
    You retrieve the exact same object twice. `Obj` and `Obj1` point to the exact same entitiy,. Doing something on `Obj1` is thus reflected on all references to that entitiy, including `Obj1`. You shopuld read about reference-types (=classes) and how to effectivly copy them. – MakePeaceGreatAgain Dec 20 '19 at 08:29
  • @HimBromBeere hmmm, then how to achieve this? I need this functionality. I need same result in 2 objects and then need to change 1 obect only. – Gulfam Dec 20 '19 at 08:32
  • @HimBromBeere, he does not want to copy the item. He still needs it in the context but without the refreshed values. – Athanasios Kataras Dec 20 '19 at 08:40

2 Answers2

3

You need to understand what the DBContext is.

Check DBContext documentation here.

While you are working in the same DBContext, it tracks the Entities you are using.

So when you retrieve the same Entity and change something, when you retrieve it from the same DBContext, it will depict the changes, even if it is in another class or service in your current application.

DBContext attach. Check the documentation of attach

Attaches the given entity to the context underlying the set. That is, the entity is placed into the context in the Unchanged state, just as if it had been read from the database.

Later on, when it is retrieved from the context it will be in the last known state.

If you want to refresh the item in the context, you can do something like the following:

Obj.State = EntityState.Detached;
Class Obj1 = DbContext.Kid(K => K.Id == 2).FirstOrDefault();

Bear in mind that the Obj will be detached and you will no longer be able to do actions with it that will propagate to the database.

Athanasios Kataras
  • 25,191
  • 4
  • 32
  • 61
  • hmmm, then how to achieve this? I need this functionality. I need same result in 2 objects and then need to change 1 obect only. – Gulfam Dec 20 '19 at 08:35
1

This is because those two "separate" objects are actually references to the same object. All objects in C# are actually references that point towards the object in memory instead of the real object. For more information about references and objects in c# :https://blog.robgarrett.com/2004/12/08/object-references-in-c/

One of the strengths of entity framework is that it is smart enough to realise that those two objects are the same object in the database. So instead of storing a copy of the object in memory it just returns the reference to the existing object.

If you want them to not match the objects you can use the AsNoTracking() from Entity Framework. See: https://learn.microsoft.com/en-us/dotnet/api/system.data.entity.dbextensions.asnotracking?view=entity-framework-5.0.0

You can use this as:

Object obj = Context.objs.Where(o => o.Id == 1).AsNoTracking().FirstOrDefault();
Joost K
  • 1,096
  • 8
  • 23
  • hmmm, then how to achieve this? I need this functionality. I need same result in 2 objects and then need to change 1 obect only. – Gulfam Dec 20 '19 at 08:35
  • 1
    See the edit, the answer from Athanasios Kataras would result in the same thing and it's a matter of preference which you use. However the one I wrote would work easier if you want this functionality with collections – Joost K Dec 20 '19 at 08:42