Table of Contents

TRLS020 — Use SaveChangesResultAsync instead of SaveChangesAsync

  • Severity: Warning
  • Category: Trellis

What it detects

Flags direct DbContext.SaveChanges() and DbContext.SaveChangesAsync() calls when Trellis.EntityFrameworkCore is referenced.

Why it matters

Raw EF Core save calls throw exceptions on database failures. Trellis save helpers keep persistence inside the Result pipeline.

Warning

The analyzer catches both sync and async saves. The code fix chooses SaveChangesResultAsync when the count is used and SaveChangesResultUnitAsync when it is discarded.

Bad example

using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

static class Example
{
    public static async Task SaveAsync(AppDbContext db, CancellationToken ct)
    {
        await db.SaveChangesAsync(ct);
    }
}

sealed class AppDbContext : DbContext
{
}

Good example

using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Trellis.EntityFrameworkCore;

static class Example
{
    public static async Task SaveAsync(AppDbContext db, CancellationToken ct)
    {
        await db.SaveChangesResultUnitAsync(ct);
    }
}

sealed class AppDbContext : DbContext
{
}

Code fix available

Yes — replaces SaveChanges or SaveChangesAsync with SaveChangesResultAsync or SaveChangesResultUnitAsync, and can add await, async, and missing using directives.

Configuration

Use standard Roslyn configuration if you need to suppress this rule in a specific scope.

dotnet_diagnostic.TRLS020.severity = none
#pragma warning disable TRLS020
// Intentional: documented exception or test-only pattern.
#pragma warning restore TRLS020
Tip

Add using Trellis.EntityFrameworkCore; and keep saves inside your Trellis pipeline so persistence errors become Result values.