Skip to main content

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​

StateMeansNext SaveChanges
ant.DetachedNot trackedNothing
ant.AddedNewINSERT
ant.UnchangedMatches what was loadedNothing
ant.ModifiedDiffers from what was loadedUPDATE
ant.DeletedMarked for removalDELETE

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.