Crash Code-11 (Sync Blob Data to EF Core)
Build a C# .NET Azure Function with a Timer Trigger. Read Blob Storage JSON, sync to an EF Core database, and track events in Azure Application Insights
888 Words [Mind Tax: 4:02m]
07 September 2026, 6:30:00 PM
Problem Description
Building a reliable SaaS-based order management service often requires background workers to sync file data into a relational database. The objective is to implement a .NET Core Azure Function that triggers every 15 minutes to ingest order data.
The function must read a JSON file from Azure Blob Storage in read-only mode, deserialize the payload, and perform an upsert (update or insert) operation on a SQL database using Entity Framework Core. Additionally, the system must maintain strict observability by tracking every created or updated order as a custom event in Azure Application Insights using dependency injection.
Sample flow
- The Azure Function is triggered by the timer chron schedule (
TimerTrigger). - The function checks the incoming string payload. If the string is not null or whitespace, it deserializes the payload into a list of orders. Otherwise, it exits early.
- The function iterates through the list and queries the database for existing records: 3.1. If the order exists, it updates the record and tracks an update event in Application Insights. 3.2. If the order does not exist, it creates a new record and tracks a creation event in Application Insights.
- The database changes are committed as a single transaction.
Input data
The JSON file containing the list of orders is injected directly into the function via the string blobString parameter using Azure Blob input bindings. The function assumes the incoming JSON string loaded from Azure Blob Storage is always well-formed JSON, an empty string, or null.
Sample content
[
{
"OrderId": 1,
"Amount": 12.34,
"Currency": "USD"
},
{
"OrderId": 2,
"Amount": 98.76,
"Currency": "EUR"
}
]
Approach
To adhere to enterprise standards and maximize performance, the solution avoids the “N+1 query problem” (executing a separate database read for every order in the loop). Instead, it reads the IDs of the incoming orders and fetches all matching existing records from the database in a single query. These existing records are mapped to a dictionary for O(1) in-memory lookups during the upsert loop.
The solution requires two main components:
- Startup Configuration: Registers the Entity Framework TaskDbContext with a Scoped lifetime for proper dependency injection.
- Function Execution: Uses constructor injection for the database context, telemetry client, and a helper interface to handle the business logic cleanly.
Code Implementation
Dependency Injection Configuration (Startup.cs)
| |
Azure Function Implementation (ImportOrdersFunction.cs)
| |
Additional Information
- Timer Trigger Format: The cron expression
0 */15 * * * *translates to “run at second 0, every 15 minutes, of every hour, every day”. - State Management: While the code utilizes
Microsoft.EntityFrameworkCore.InMemoryfor testing parameters, switching to SQL Server or PostgreSQL in production only requires updating theStartupbuilder options. The upsert logic inside the function remains unchanged. - Telemetry Setup: The
TelemetryClientautomatically batches custom tracking events and transmits them asynchronously to Azure App Insights, preventing network bottlenecks during the execution loop.
Complexity Analysis
- Time Complexity:
O(N)whereNis the number of orders in the parsed JSON. Retrieving existing records using.Contains()scales highly efficiently in SQL. The dictionary lookups execute inO(1)time per record. Saving all records using.SaveChangesAsync()reduces the network roundtrip overhead to a constant time factor compared to saving incrementally inside the loop. - Space/Memory Complexity:
O(N)whereNis the number of incoming records. The function holds the deserialized list, the list of identifiers, and the dictionary of database-matched items in memory concurrently before garbage collection safely drops them at the end of the invocation.