How Does the Entity Framework ChangeTracker know that a property has changed?
How does the Entity Framework ChangeTracker know that a property has changed? The properties have no advanced setter. I would like to know how to track those changes.
entity-framework change-tracking
add a comment |
How does the Entity Framework ChangeTracker know that a property has changed? The properties have no advanced setter. I would like to know how to track those changes.
entity-framework change-tracking
It keeps internally a snapshot of the last retrieved/applied properties.
– Ivan Stoev
Nov 27 '18 at 9:48
add a comment |
How does the Entity Framework ChangeTracker know that a property has changed? The properties have no advanced setter. I would like to know how to track those changes.
entity-framework change-tracking
How does the Entity Framework ChangeTracker know that a property has changed? The properties have no advanced setter. I would like to know how to track those changes.
entity-framework change-tracking
entity-framework change-tracking
asked Nov 27 '18 at 9:09
Sascha SanfteilSascha Sanfteil
83
83
It keeps internally a snapshot of the last retrieved/applied properties.
– Ivan Stoev
Nov 27 '18 at 9:48
add a comment |
It keeps internally a snapshot of the last retrieved/applied properties.
– Ivan Stoev
Nov 27 '18 at 9:48
It keeps internally a snapshot of the last retrieved/applied properties.
– Ivan Stoev
Nov 27 '18 at 9:48
It keeps internally a snapshot of the last retrieved/applied properties.
– Ivan Stoev
Nov 27 '18 at 9:48
add a comment |
1 Answer
1
active
oldest
votes
If you use the DbContext and DbSets normally, you won't add items to the change tracker. Before you can change any property of an entity, you'll first have to fetch it. Also if you want to delete it, you'll first have to fetch it.
The change tracker holds all fetched items, at least until SaveChanges, but probably until the DbContext is Disposed, if you really want to know, write some test code.
The ChangeTracker also holds all Added items.
The sequence of fetched and added items in the ChangeTracker can be accessed using method Entries
or Entries<...>
. The returned value is a sequence of DbEntityEntries
. Every DbEntityEntry
has a State, indicating whether it was Added / Deleted / Modified / Unchanged
After you fetched the item, its state is Unchanged. If you call Delete, the state changes in Deleted. If you add an object the State if Added. The difficult pare is Modified, because you can modify an item without using DbSet:
// Student moves to different school:
int jfkSchoolId = schoolContext.Schools
.Where(school => school.Name = "J.F. Kennedy School")
.Select(school => school.Id)
.FirstOrDefault();
var student = schoolContext.Students.Where(student.Id == 100).SingleOrDefault();
student.SchoolId = jfkSchoolId;
How does the ChangeTracker know you changed the SchoolId?
Luckily, the DbEntityEntry holds the original database values as well as the current values. So when you ask for the state, all it has to do is check if it has been added / deleted / etc. Most states are easy, only if it is Unchanged, the function that fetches the state will have to check all original values with all currentValues, using a default value comparer. If there are differences, the state is marked Changed, so the next time the value comparison is not needed.
You can't undo this: once the State is changed, you can't unchange it:
int originalSchoolId = myStudent.SchoolId;
myStudent.SchoolId = jfxSchoolId;
var state = dbContext.ChangeTracker.Entries<Students>
.Where(studentEntity => studentEntity.Entity.Id == myStudent.Id)
.Select(studentEntity => studentEntity.State)
.SingleOrDefault();
// state equals Changed, because original value was not 0
// student back to original school
myStudent.SchoolId = originalSchoolId;
// ask the state of this student again:
state = ...
// state is still changed
Good answer! Thank you.
– Sascha Sanfteil
Nov 27 '18 at 11:07
It becomes complicated once you start Attaching / Detaching items directly, instead of fetching an item. I see people to this regularly, but I think it is bad practice, especially if you keep in mind that several people might change your database.
– Harald Coppoolse
Nov 27 '18 at 11:11
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53496109%2fhow-does-the-entity-framework-changetracker-know-that-a-property-has-changed%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
If you use the DbContext and DbSets normally, you won't add items to the change tracker. Before you can change any property of an entity, you'll first have to fetch it. Also if you want to delete it, you'll first have to fetch it.
The change tracker holds all fetched items, at least until SaveChanges, but probably until the DbContext is Disposed, if you really want to know, write some test code.
The ChangeTracker also holds all Added items.
The sequence of fetched and added items in the ChangeTracker can be accessed using method Entries
or Entries<...>
. The returned value is a sequence of DbEntityEntries
. Every DbEntityEntry
has a State, indicating whether it was Added / Deleted / Modified / Unchanged
After you fetched the item, its state is Unchanged. If you call Delete, the state changes in Deleted. If you add an object the State if Added. The difficult pare is Modified, because you can modify an item without using DbSet:
// Student moves to different school:
int jfkSchoolId = schoolContext.Schools
.Where(school => school.Name = "J.F. Kennedy School")
.Select(school => school.Id)
.FirstOrDefault();
var student = schoolContext.Students.Where(student.Id == 100).SingleOrDefault();
student.SchoolId = jfkSchoolId;
How does the ChangeTracker know you changed the SchoolId?
Luckily, the DbEntityEntry holds the original database values as well as the current values. So when you ask for the state, all it has to do is check if it has been added / deleted / etc. Most states are easy, only if it is Unchanged, the function that fetches the state will have to check all original values with all currentValues, using a default value comparer. If there are differences, the state is marked Changed, so the next time the value comparison is not needed.
You can't undo this: once the State is changed, you can't unchange it:
int originalSchoolId = myStudent.SchoolId;
myStudent.SchoolId = jfxSchoolId;
var state = dbContext.ChangeTracker.Entries<Students>
.Where(studentEntity => studentEntity.Entity.Id == myStudent.Id)
.Select(studentEntity => studentEntity.State)
.SingleOrDefault();
// state equals Changed, because original value was not 0
// student back to original school
myStudent.SchoolId = originalSchoolId;
// ask the state of this student again:
state = ...
// state is still changed
Good answer! Thank you.
– Sascha Sanfteil
Nov 27 '18 at 11:07
It becomes complicated once you start Attaching / Detaching items directly, instead of fetching an item. I see people to this regularly, but I think it is bad practice, especially if you keep in mind that several people might change your database.
– Harald Coppoolse
Nov 27 '18 at 11:11
add a comment |
If you use the DbContext and DbSets normally, you won't add items to the change tracker. Before you can change any property of an entity, you'll first have to fetch it. Also if you want to delete it, you'll first have to fetch it.
The change tracker holds all fetched items, at least until SaveChanges, but probably until the DbContext is Disposed, if you really want to know, write some test code.
The ChangeTracker also holds all Added items.
The sequence of fetched and added items in the ChangeTracker can be accessed using method Entries
or Entries<...>
. The returned value is a sequence of DbEntityEntries
. Every DbEntityEntry
has a State, indicating whether it was Added / Deleted / Modified / Unchanged
After you fetched the item, its state is Unchanged. If you call Delete, the state changes in Deleted. If you add an object the State if Added. The difficult pare is Modified, because you can modify an item without using DbSet:
// Student moves to different school:
int jfkSchoolId = schoolContext.Schools
.Where(school => school.Name = "J.F. Kennedy School")
.Select(school => school.Id)
.FirstOrDefault();
var student = schoolContext.Students.Where(student.Id == 100).SingleOrDefault();
student.SchoolId = jfkSchoolId;
How does the ChangeTracker know you changed the SchoolId?
Luckily, the DbEntityEntry holds the original database values as well as the current values. So when you ask for the state, all it has to do is check if it has been added / deleted / etc. Most states are easy, only if it is Unchanged, the function that fetches the state will have to check all original values with all currentValues, using a default value comparer. If there are differences, the state is marked Changed, so the next time the value comparison is not needed.
You can't undo this: once the State is changed, you can't unchange it:
int originalSchoolId = myStudent.SchoolId;
myStudent.SchoolId = jfxSchoolId;
var state = dbContext.ChangeTracker.Entries<Students>
.Where(studentEntity => studentEntity.Entity.Id == myStudent.Id)
.Select(studentEntity => studentEntity.State)
.SingleOrDefault();
// state equals Changed, because original value was not 0
// student back to original school
myStudent.SchoolId = originalSchoolId;
// ask the state of this student again:
state = ...
// state is still changed
Good answer! Thank you.
– Sascha Sanfteil
Nov 27 '18 at 11:07
It becomes complicated once you start Attaching / Detaching items directly, instead of fetching an item. I see people to this regularly, but I think it is bad practice, especially if you keep in mind that several people might change your database.
– Harald Coppoolse
Nov 27 '18 at 11:11
add a comment |
If you use the DbContext and DbSets normally, you won't add items to the change tracker. Before you can change any property of an entity, you'll first have to fetch it. Also if you want to delete it, you'll first have to fetch it.
The change tracker holds all fetched items, at least until SaveChanges, but probably until the DbContext is Disposed, if you really want to know, write some test code.
The ChangeTracker also holds all Added items.
The sequence of fetched and added items in the ChangeTracker can be accessed using method Entries
or Entries<...>
. The returned value is a sequence of DbEntityEntries
. Every DbEntityEntry
has a State, indicating whether it was Added / Deleted / Modified / Unchanged
After you fetched the item, its state is Unchanged. If you call Delete, the state changes in Deleted. If you add an object the State if Added. The difficult pare is Modified, because you can modify an item without using DbSet:
// Student moves to different school:
int jfkSchoolId = schoolContext.Schools
.Where(school => school.Name = "J.F. Kennedy School")
.Select(school => school.Id)
.FirstOrDefault();
var student = schoolContext.Students.Where(student.Id == 100).SingleOrDefault();
student.SchoolId = jfkSchoolId;
How does the ChangeTracker know you changed the SchoolId?
Luckily, the DbEntityEntry holds the original database values as well as the current values. So when you ask for the state, all it has to do is check if it has been added / deleted / etc. Most states are easy, only if it is Unchanged, the function that fetches the state will have to check all original values with all currentValues, using a default value comparer. If there are differences, the state is marked Changed, so the next time the value comparison is not needed.
You can't undo this: once the State is changed, you can't unchange it:
int originalSchoolId = myStudent.SchoolId;
myStudent.SchoolId = jfxSchoolId;
var state = dbContext.ChangeTracker.Entries<Students>
.Where(studentEntity => studentEntity.Entity.Id == myStudent.Id)
.Select(studentEntity => studentEntity.State)
.SingleOrDefault();
// state equals Changed, because original value was not 0
// student back to original school
myStudent.SchoolId = originalSchoolId;
// ask the state of this student again:
state = ...
// state is still changed
If you use the DbContext and DbSets normally, you won't add items to the change tracker. Before you can change any property of an entity, you'll first have to fetch it. Also if you want to delete it, you'll first have to fetch it.
The change tracker holds all fetched items, at least until SaveChanges, but probably until the DbContext is Disposed, if you really want to know, write some test code.
The ChangeTracker also holds all Added items.
The sequence of fetched and added items in the ChangeTracker can be accessed using method Entries
or Entries<...>
. The returned value is a sequence of DbEntityEntries
. Every DbEntityEntry
has a State, indicating whether it was Added / Deleted / Modified / Unchanged
After you fetched the item, its state is Unchanged. If you call Delete, the state changes in Deleted. If you add an object the State if Added. The difficult pare is Modified, because you can modify an item without using DbSet:
// Student moves to different school:
int jfkSchoolId = schoolContext.Schools
.Where(school => school.Name = "J.F. Kennedy School")
.Select(school => school.Id)
.FirstOrDefault();
var student = schoolContext.Students.Where(student.Id == 100).SingleOrDefault();
student.SchoolId = jfkSchoolId;
How does the ChangeTracker know you changed the SchoolId?
Luckily, the DbEntityEntry holds the original database values as well as the current values. So when you ask for the state, all it has to do is check if it has been added / deleted / etc. Most states are easy, only if it is Unchanged, the function that fetches the state will have to check all original values with all currentValues, using a default value comparer. If there are differences, the state is marked Changed, so the next time the value comparison is not needed.
You can't undo this: once the State is changed, you can't unchange it:
int originalSchoolId = myStudent.SchoolId;
myStudent.SchoolId = jfxSchoolId;
var state = dbContext.ChangeTracker.Entries<Students>
.Where(studentEntity => studentEntity.Entity.Id == myStudent.Id)
.Select(studentEntity => studentEntity.State)
.SingleOrDefault();
// state equals Changed, because original value was not 0
// student back to original school
myStudent.SchoolId = originalSchoolId;
// ask the state of this student again:
state = ...
// state is still changed
answered Nov 27 '18 at 10:55
Harald CoppoolseHarald Coppoolse
12.6k12961
12.6k12961
Good answer! Thank you.
– Sascha Sanfteil
Nov 27 '18 at 11:07
It becomes complicated once you start Attaching / Detaching items directly, instead of fetching an item. I see people to this regularly, but I think it is bad practice, especially if you keep in mind that several people might change your database.
– Harald Coppoolse
Nov 27 '18 at 11:11
add a comment |
Good answer! Thank you.
– Sascha Sanfteil
Nov 27 '18 at 11:07
It becomes complicated once you start Attaching / Detaching items directly, instead of fetching an item. I see people to this regularly, but I think it is bad practice, especially if you keep in mind that several people might change your database.
– Harald Coppoolse
Nov 27 '18 at 11:11
Good answer! Thank you.
– Sascha Sanfteil
Nov 27 '18 at 11:07
Good answer! Thank you.
– Sascha Sanfteil
Nov 27 '18 at 11:07
It becomes complicated once you start Attaching / Detaching items directly, instead of fetching an item. I see people to this regularly, but I think it is bad practice, especially if you keep in mind that several people might change your database.
– Harald Coppoolse
Nov 27 '18 at 11:11
It becomes complicated once you start Attaching / Detaching items directly, instead of fetching an item. I see people to this regularly, but I think it is bad practice, especially if you keep in mind that several people might change your database.
– Harald Coppoolse
Nov 27 '18 at 11:11
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53496109%2fhow-does-the-entity-framework-changetracker-know-that-a-property-has-changed%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
It keeps internally a snapshot of the last retrieved/applied properties.
– Ivan Stoev
Nov 27 '18 at 9:48