find-slow-queries.sql — top CPU/IO hogs in SQL Server
Query the plan cache to find worst-performing queries by CPU, elapsed time, or logical reads. Runs on any SQL Server 2012+.
-- Top 20 queries by total CPU time SELECT TOP 20 SUBSTRING(qt.text, (qs.statement_start_offset/2)+1, ((CASE qs.statement_end_offset WHEN -1 THEN DATALENGTH(qt.text) ELSE qs.statement_end_offset END - qs.statement_start_offset)/2)+1) AS query_text, qs.execution_count, qs.total_worker_time / 1000 AS total_cpu_ms, qs.total_worker_time / qs.execution_count / 1000 AS avg_cpu_ms, qs.total_elapsed_time / 1000 AS total_elapsed_ms, qs.total_logical_reads, qp.query_plan FROM sys.dm_exec_query_stats qs CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) qt CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp ORDER BY qs.total_worker_time DESC;
index-fragmentation.sql — check and fix index health
Check index fragmentation and generate the correct maintenance command. Reorganize under 30%, rebuild above.
SELECT OBJECT_NAME(i.object_id) AS table_name, i.name AS index_name, s.avg_fragmentation_in_percent, s.page_count, CASE WHEN s.avg_fragmentation_in_percent > 30 THEN 'REBUILD' WHEN s.avg_fragmentation_in_percent > 10 THEN 'REORGANIZE' ELSE 'OK' END AS recommended_action FROM sys.dm_db_index_physical_stats( DB_ID(), NULL, NULL, NULL, 'LIMITED') s JOIN sys.indexes i ON s.object_id = i.object_id AND s.index_id = i.index_id WHERE s.page_count > 100 AND i.name IS NOT NULL ORDER BY s.avg_fragmentation_in_percent DESC;
OrderRepository.cs — async repository pattern with Dapper
Clean async service + repository pattern using Dapper for SQL Server. Lightweight, testable, and doesn't fight the ORM.
public interface IOrderRepository { Task<IEnumerable<Order>> GetPendingOrdersAsync(CancellationToken ct); Task<Order?> GetByIdAsync(int orderId, CancellationToken ct); } public class OrderRepository(IConfiguration cfg) : IOrderRepository { private readonly string _conn = cfg.GetConnectionString("WmsDb")!; public async Task<IEnumerable<Order>> GetPendingOrdersAsync(CancellationToken ct) { await using var db = new SqlConnection(_conn); return await db.QueryAsync<Order>(new CommandDefinition( """ SELECT OrderId, CustomerId, Status, CreatedAt FROM dbo.Orders WHERE Status = 'PENDING' ORDER BY CreatedAt ASC """, cancellationToken: ct)); } public async Task<Order?> GetByIdAsync(int orderId, CancellationToken ct) { await using var db = new SqlConnection(_conn); return await db.QueryFirstOrDefaultAsync<Order>(new CommandDefinition( "SELECT * FROM dbo.Orders WHERE OrderId = @OrderId", new { OrderId = orderId }, cancellationToken: ct)); } }
GlobalExceptionMiddleware.cs — centralized error handling
Global exception middleware for ASP.NET Core APIs. Catches unhandled exceptions, logs them, and returns a consistent JSON error response.
public class GlobalExceptionMiddleware(RequestDelegate next, ILogger<GlobalExceptionMiddleware> logger) { public async Task InvokeAsync(HttpContext ctx) { try { await next(ctx); } catch (Exception ex) { logger.LogError(ex, "Unhandled exception on {Method} {Path}", ctx.Request.Method, ctx.Request.Path); ctx.Response.StatusCode = StatusCodes.Status500InternalServerError; ctx.Response.ContentType = "application/json"; await ctx.Response.WriteAsJsonAsync(new { status = 500, title = "An unexpected error occurred", traceId = Activity.Current?.Id ?? ctx.TraceIdentifier }); } } } // Register in Program.cs — must come first app.UseMiddleware<GlobalExceptionMiddleware>();
deadlock-monitor.sql — catch deadlocks from system_health XE
Extract deadlock graphs from SQL Server's always-on system_health Extended Events session. No trace flags needed.
WITH DeadlockData AS ( SELECT xdr.value('(//deadlock/process-list/process/@lastbatchstarted)[1]', 'datetime2') AS deadlock_time, xdr.value('(//deadlock/process-list/process/@hostname)[1]', 'nvarchar(256)') AS hostname, xdr.query('.') AS deadlock_xml FROM ( SELECT CAST(target_data AS xml) AS target_data FROM sys.dm_xe_session_targets t JOIN sys.dm_xe_sessions s ON t.event_session_address = s.address WHERE s.name = 'system_health' AND t.target_name = 'ring_buffer' ) AS src CROSS APPLY target_data.nodes('//RingBufferTarget/event[@name="xml_deadlock_report"]') AS n(xdr) ) SELECT * FROM DeadlockData ORDER BY deadlock_time DESC;
PluginBase.cs — MS Dynamics 365 plugin base class
Boilerplate base class for Dynamics 365 plugins — wraps the service provider setup so you don't repeat it every time.
public abstract class PluginBase : IPlugin { public void Execute(IServiceProvider serviceProvider) { var context = (IPluginExecutionContext) serviceProvider.GetService(typeof(IPluginExecutionContext)); var factory = (IOrganizationServiceFactory) serviceProvider.GetService(typeof(IOrganizationServiceFactory)); var service = factory.CreateOrganizationService(context.UserId); var tracer = (ITracingService) serviceProvider.GetService(typeof(ITracingService)); try { ExecutePlugin(context, service, tracer); } catch (InvalidPluginExecutionException) { throw; } catch (Exception ex) { tracer.Trace($"Plugin error: {ex.Message}"); throw new InvalidPluginExecutionException($"Unexpected: {ex.Message}", ex); } } protected abstract void ExecutePlugin( IPluginExecutionContext context, IOrganizationService service, ITracingService tracer); }
git-rescue.sh — commands you need when things go sideways
The git commands I reach for constantly — not the basics, the ones that save you when things go wrong.
# Undo last commit but keep changes staged git reset --soft HEAD~1 # Undo last commit AND unstage (still keep files) git reset --mixed HEAD~1 # Completely discard last commit (DESTRUCTIVE) git reset --hard HEAD~1 # Stash with a descriptive label git stash push -m "WIP: order processor refactor" # Cherry-pick a single commit from another branch git cherry-pick abc1234 # Binary search for the commit that introduced a bug git bisect start git bisect bad # current is broken git bisect good v2.1.0 # last known good tag # Rewrite last 3 commit messages interactively git rebase -i HEAD~3
Always use
SET NOCOUNT ON in stored proceduresWithout it, SQL Server sends a row count message for every DML statement, which can confuse ORMs and adds needless network chatter. Put it at the top of every stored proc — it's free performance.
Never use
SELECT * in production queriesIt prevents index-only scans, breaks when columns are added/reordered, and pulls unnecessary data. Always name your columns. In a WMS with wide tables (50+ columns), this is the difference between a 2ms and a 200ms query.
Use
IAsyncEnumerable for streaming large result setsInstead of loading 100k rows into a
List<T>, return IAsyncEnumerable<T>. ASP.NET Core will stream JSON as rows arrive. Dapper supports this via QueryUnbufferedAsync.Use
WITH (NOLOCK) carefully — it's not freeNOLOCK lets reads bypass locking but you can get dirty reads. Use it on reporting queries, never on anything that makes a business decision. The real answer is READ_COMMITTED_SNAPSHOT at the database level.In Dynamics plugins, always check
InputParameters.ContainsKeyPlugins fire on multiple message types and the target entity may not always have the attribute you expect. Check
context.InputParameters.ContainsKey("Target") defensively. Uncaught cast exceptions in a sync plugin break the user's form with a cryptic error.Avoid
async void — it's an exception black holeasync void methods (other than event handlers) swallow exceptions silently and can crash your app in unpredictable ways. Always use async Task.Covering indexes beat query rewrites most of the time
Before rewriting a slow query, check if a covering index can solve it. Add filter columns as the key,
INCLUDE the selected columns. SQL Server satisfies the whole query from the index without touching the base table.Pass
CancellationToken everywhere in ASP.NET CoreForward the token all the way to your DB calls. When a client disconnects, the token fires and aborts the DB query. On a WMS with long-running batch queries this prevents thread pile-ups under load.
📖 ASP.NET & C# Docs
ASP.NET Core Documentation
learn.microsoft.com/aspnet/core
→
C# Language Reference
learn.microsoft.com/dotnet/csharp
→
Dapper — micro-ORM for SQL Server
github.com/DapperLib/Dapper
→
🗄️ SQL Server Resources
SQL Server Central
sqlservercentral.com
→
Brent Ozar — sp_Blitz Free Scripts
brentozar.com — best free SQL Server health check
→
Use The Index, Luke!
use-the-index-luke.com — SQL indexing explained
→