Entity states
Every entity a context knows about has a state. Usually ant manages that for you, and these calls are for the times you need to say it yourself.
The states
| State | Means | Next SaveChanges |
|---|---|---|
ant.Detached | Not tracked | Nothing |
ant.Added | New | INSERT |
ant.Unchanged | Matches what was loaded | Nothing |
ant.Modified | Differs from what was loaded | UPDATE |
ant.Deleted | Marked for removal | DELETE |
Changing state
err := ant.Add(db, newUser) // insert on the next save
err = ant.Remove(db, user) // delete on the next save
err = ant.Attach(db, existing) // track as it is, assumed saved
err = ant.MarkModified(db, disconnect) // write every field on the next save
ant.Detach(db, user) // stop tracking, forget changes
db.ClearTracked() // forget everything
MarkModified suits a struct from outside, such as a request body, whose earlier values are unknown.
Looking inside
ant.Entry tells you what the tracker knows.
entry := ant.Entry(db, user)
fmt.Println(entry.State()) // Modified
fmt.Println(entry.Changed()) // [Age]
dirty := ant.IsDirty(entry, &U.Age)
before, err := ant.Original(entry, &U.Age)
ant.Tracked[User](db) lists tracked entities, oldest first, and db.DebugTracked() prints the tracker as text.
Saving a graph from outside
ant.TrackGraph saves a tree that came from outside, like a request body. Nothing says what it held before, so your function decides each entity's state.
err := ant.TrackGraph(db, incoming, func(n ant.GraphNode) ant.State {
if n.HasKey {
return ant.Modified
}
return ant.Added
})
err = db.SaveChanges(ctx)
Foreign keys are filled in as it walks. Returning ant.Detached skips an entity and everything below it.
See it tested: tests/features/change_tracking/states_test.go