To see the behaviour of the different APIs, the examples below uses the following data models:
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int? Age { get; set; }
}
public class Track
{
[AutoIncrement]
public int Id { get; set; }
public string Name { get; set; }
public int ArtistId { get; set; }
public string Album { get; set; }
public int Year { get; set; }
public override string ToString() => Name;
}
Updates​
Updating any model without any filters will update every field, except the Id which is used to filter the update to this specific record:
db.Update(new Person { Id = 1, FirstName = "Jimi", LastName = "Hendrix", Age = 27});
Example updating existing data model in-place:
var alive = db.Single<Track>(x => x.Name == "Alive");
alive.Name = "Still Alive";
alive.Year = 2000;
db.Update(alive); // Updates all fields except `Id` which is used to filter
var updatedTrackById = db.SingleById<Track>(alive.Id);
If you supply your own where expression, it updates every field (inc. Id) but uses your filter instead:
db.Update(new Person { Id = 1, FirstName = "JJ" }, p => p.LastName == "Hendrix");
One way to limit the fields which gets updated is to use an Anonymous Type:
db.Update<Person>(new { FirstName = "JJ" }, p => p.LastName == "Hendrix");
Updates ALL fields matching specified filter:
db.Update(new Track { Id = 20, Name = "Partially Alive...", ArtistId = alive.ArtistId },
where: x => x.Name == "Still Alive...");
Or by using UpdateNonDefaults
which only updates the non-default values in your model using the filter specified:
db.UpdateNonDefaults(new Person { FirstName = "JJ" }, p => p.LastName == "Hendrix");
Update only fields in anonymous type:
db.Update<Track>(new { Year = 2000 }, where: x => x.Id == 20);
Multi update example:
var pearlJamTracks = db.Select<Track>(x => x.ArtistId == alive.ArtistId);
pearlJamTracks.Each(x => x.Album = "Rear View Mirror (Greatest Hits 1991–2003)");
db.Update(pearlJamTracks[0], pearlJamTracks[1]); //Update by params
UpdateOnly​
As updating a partial row is a common use-case in Db's, we've added a number of methods for just this purpose, named UpdateOnly.
The lambda syntax lets you update only the fields listed in property initializers, e.g:
db.UpdateOnly(() => new Person { FirstName = "JJ" });
The second argument lets you specify a filter for updates:
db.UpdateOnly(() => new Person { FirstName = "JJ" }, where: p => p.LastName == "Hendrix");
Alternatively you can pass in a POCO directly, in which case the first expression in an UpdateOnlyFields
statement is used to specify which fields should be updated:
db.UpdateOnlyFields(new Person { FirstName = "JJ" }, onlyFields: p => p.FirstName);
db.UpdateOnlyFields(new Person { FirstName = "JJ", Age = 12 },
onlyFields: p => new { p.FirstName, p.Age });
db.UpdateOnlyFields(new Person { FirstName = "JJ", Age = 12 },
onlyFields: p => new[] { "Name", "Age" });
When present, the second expression is used as the where filter:
db.UpdateOnlyFields(new Person { FirstName = "JJ" },
onlyFields: p => p.FirstName,
where: p => p.LastName == "Hendrix");
Instead of using the expression filters above you can choose to use an SqlExpression builder which provides more flexibility when you want to programmatically construct the update statement:
var q = db.From<Person>()
.Update(p => p.FirstName);
db.UpdateOnlyFields(new Person { FirstName = "JJ", LastName = "Hendo" }, onlyFields: q);
Using an Object Dictionary:
var updateFields = new Dictionary<string,object> {
[nameof(Person.FirstName)] = "JJ",
};
db.UpdateOnly<Person>(updateFields, p => p.LastName == "Hendrix");
Using a typed SQL Expression:
var q = db.From<Person>()
.Where(x => x.FirstName == "Jimi")
.Update(p => p.FirstName);
db.UpdateOnlyFields(new Person { FirstName = "JJ" }, onlyFields: q);
Updating existing values​
The UpdateAdd
API provides several Typed API's for updating existing values:
//Increase everyone's Score by 3 points
db.UpdateAdd(() => new Person { Score = 3 });
//Remove 5 points from Jackson Score
db.UpdateAdd(() => new Person { Score = -5 }, where: x => x.LastName == "Jackson");
//Graduate everyone and increase everyone's Score by 2 points
db.UpdateAdd(() => new Person { Points = 2, Graduated = true });
//Add 10 points to Michael's score
var q = db.From<Person>()
.Where(x => x.FirstName == "Michael");
db.UpdateAdd(() => new Person { Points = 10 }, q);
//UpdateAdd on non-numeric fields are updated normally:
db.UpdateAdd(() => new Track { Year = -10, Album = "Lost a decade" }, x => x.Year == 1997);
//Add 10 years to all 1991 Tracks
var q = db.From<Track>()
.Where(x => x.Year == 1991);
db.UpdateAdd(() => new Track { Year = 10 }, q);
INFO
Any non-numeric values in an UpdateAdd
statement (e.g. strings) are replaced as normal.
Update by Dictionary​
Person row = db.SingleById<Person>(row.Id);
var obj = row.ToObjectDictionary();
obj[nameof(Person.LastName)] = "Smith";
db.Update<Person>(obj);
UpdateOnly by Dictionary​
// By Primary Key Id
var fields = new Dictionary<string, object> {
[nameof(Person.Id)] = 1,
[nameof(Person.FirstName)] = "John",
[nameof(Person.LastName)] = null,
};
db.UpdateOnly<Person>(fields);
// By Custom Where Expression
var fields = new Dictionary<string, object> {
[nameof(Person.FirstName)] = "John",
[nameof(Person.LastName)] = null,
};
db.UpdateOnly<Person>(fields, p => p.LastName == "Hendrix");