Skip to content

The search box knows all the secrets -- try it!

Polecat is part of the Critter Stack ecosystem.

JasperFx Logo JasperFx provides formal support for Polecat and other Critter Stack libraries. Please check our Support Plans for more details.

Partial Updates / Patching ​

Polecat provides a patching API for making targeted updates to documents without loading and re-saving the entire document. Under the hood, this uses SQL Server's JSON_MODIFY() function.

Basic Usage ​

cs
// Patch a document by ID
session.Patch<Order>(orderId)
    .Set(x => x.Status, "Shipped");

await session.SaveChangesAsync();

Available Operations ​

Set a Value ​

cs
session.Patch<Order>(orderId)
    .Set(x => x.Status, "Completed")
    .Set(x => x.ShippedDate, DateTimeOffset.UtcNow);

Set nested properties:

cs
session.Patch<Order>(orderId)
    .Set(x => x.Address.City, "New York");

Increment a Numeric Value ​

cs
session.Patch<Order>(orderId)
    .Increment(x => x.ItemCount, 1);

// Decrement by using a negative value
session.Patch<Order>(orderId)
    .Increment(x => x.ItemCount, -1);

Append to a Collection ​

cs
session.Patch<Order>(orderId)
    .Append(x => x.Tags, "priority");

Append only if the value doesn't already exist:

cs
session.Patch<Order>(orderId)
    .AppendIfNotExists(x => x.Tags, "priority");

Insert at a Specific Position ​

cs
session.Patch<Order>(orderId)
    .Insert(x => x.Tags, "urgent", index: 0);

Remove from a Collection ​

cs
session.Patch<Order>(orderId)
    .Remove(x => x.Tags, "obsolete");

Duplicate a Value ​

Copy a value to multiple destinations:

cs
session.Patch<Order>(orderId)
    .Duplicate(x => x.BillingAddress, x => x.ShippingAddress);

Rename a Property ​

cs
session.Patch<Order>(orderId)
    .Rename("oldPropertyName", x => x.NewPropertyName);

Delete a Property ​

cs
session.Patch<Order>(orderId)
    .Delete("obsoleteField");

// Or via expression
session.Patch<Order>(orderId)
    .Delete(x => x.ObsoleteField);

Patching with a Where Clause ​

Apply patches to multiple documents matching a condition:

cs
session.Patch<Order>(x => x.Status == "Pending")
    .Set(x => x.Status, "Cancelled");

await session.SaveChangesAsync();

How It Works ​

Each patch operation generates a SQL UPDATE statement using JSON_MODIFY():

sql
UPDATE pc_doc_order
SET data = JSON_MODIFY(data, '$.status', 'Shipped')
WHERE id = @id

For collection operations, Polecat uses OPENJSON and STRING_AGG to manipulate JSON arrays.

TIP

Patching is more efficient than loading, modifying, and re-saving a document because only the changed values are sent to the database, and it doesn't require reading the full document first.

Released under the MIT License.