<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/milan-jovanovi--lmrqyshnk" -->

---
title: Milan Jovanović | daily.dev
description: A benchmarked comparison of seven approaches for bulk updating rows in PostgreSQL from .NET, where each row requires a unique value (e.g., a per-row...
canonical: https://daily.dev/posts/milan-jovanovi--lmrqyshnk
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Milan Jovanović | daily.dev
og:description: A benchmarked comparison of seven approaches for bulk updating rows in PostgreSQL from .NET, where each row requires a unique value (e.g., a per-row...
og:url: https://daily.dev/posts/milan-jovanovi--lmrqyshnk
og:image: https://api.daily.dev/og/posts/lmrQYSHNk.png
og:image:alt: Milan Jovanović
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Milan Jovanović

**[Milan Jovanović](https://daily.dev/sources/milanjovanovic)** · 12 min read · 2 upvotes · 0 comments

## Summary

A benchmarked comparison of seven approaches for bulk updating rows in PostgreSQL from .NET, where each row requires a unique value (e.g., a per-row timestamp). The scenario involves marking orders as processed with individual timestamps. Results at 10,000 rows range from 2,414ms (naive per-row Dapper loop) down to 41ms (UNNEST or binary COPY). Key findings: round-trips are the primary bottleneck, not SQL execution speed. EF Core SaveChanges batches statements but still generates N individual UPDATEs. Single-statement approaches using a VALUES table, CTE, UNNEST, or temp table + binary COPY dramatically outperform. For PostgreSQL specifically, UNNEST (fixed query text, two array parameters, stable query plans) and binary COPY (no parameter limits, best for very large batches) are the recommended approaches. Dapper and EF Core can be mixed within the same transaction.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://www.milanjovanovic.tech/blog/optimizing-bulk-database-updates-in-dotnet>

## Similar posts on daily.dev

- [Fastest Way to Bulk Insert Thousands of Rows in EF Core](https://daily.dev/posts/fastest-way-to-bulk-insert-thousands-of-rows-in-ef-core-uym6xxs1m) · Code with Mukesh · 8 upvotes · 2 comments
- [Insane Performance Boost in EF Core using Entity Framework Extensions](https://daily.dev/posts/insane-performance-boost-in-ef-core-using-entity-framework-extensions-r3pbiriw6) · We Are .NET · 4 upvotes · 0 comments

---

Tags: [#.net](https://daily.dev/tags/.net), [#postgresql](https://daily.dev/tags/postgresql)

[View this post on daily.dev](https://daily.dev/posts/milan-jovanovi--lmrqyshnk)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Milan Jovanović","url":"https://daily.dev/posts/milan-jovanovi--lmrqyshnk","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/milan-jovanovi--lmrqyshnk"},"datePublished":"2026-03-13T21:32:09.415Z","dateModified":"2026-03-13T21:32:38.087Z","description":"A benchmarked comparison of seven approaches for bulk updating rows in PostgreSQL from .NET, where each row requires a unique value (e.g., a per-row...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/89bba1a188f4854b7d09e5b163efc963?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/89bba1a188f4854b7d09e5b163efc963?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Milan Jovanović","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Milan Jovanović","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/78d8abfb692746538410dee47f93e566","url":"https://daily.dev/sources/milanjovanovic"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/milan-jovanovi--lmrqyshnk","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":2},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":".net,postgresql","timeRequired":"PT12M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Milan Jovanović","item":"https://daily.dev/sources/milanjovanovic"},{"@type":"ListItem","position":3,"name":"Milan Jovanović"}]}
```

