Skip to main content

Free 30-min security demo  — We'll scan your real code and show live findings, no commitment Book Now

Offensive360
Application Security

dotnet ef Roslyn Analyzer Error: The Fix

dotnet ef database update failing from Roslyn analyzer errors? Add -- /p:RunAnalyzersDuringBuild=false. Variants, CI/CD patterns and troubleshooting inside.

Offensive360 Security Research Team — min read
dotnet ef RunAnalyzersDuringBuild dotnet ef migrations dotnet ef database update Roslyn analyzers .NET static code analysis Entity Framework dotnet ef RunAnalyzersDuringBuild=false dotnet ef migrations add dotnet build analyzers SAST .NET security CI/CD dotnet ef -- /p:RunAnalyzersDuringBuild=false

Problem: You run dotnet ef migrations add or dotnet ef database update and it fails — not because of a migration issue, but because of a Roslyn analyzer error in your project. The build log shows analyzer warnings treated as errors (CA2100, CS8600, or similar), and the EF command aborts before it even finds your DbContext.

Solution: Pass RunAnalyzersDuringBuild=false to the underlying MSBuild invocation using the -- separator:

# The fix — pass MSBuild property through the -- separator
dotnet ef migrations add MyMigration -- /p:RunAnalyzersDuringBuild=false
dotnet ef database update -- /p:RunAnalyzersDuringBuild=false

This disables Roslyn analyzer execution only for the EF tool’s internal build — not for your main application build. Your security-gated CI pipeline stays intact.

This post explains exactly why dotnet ef triggers your analyzers, every command variant that works, and how to structure your CI/CD pipeline so analyzers run on your application code but not on the EF design-time build.


Why dotnet ef Triggers Roslyn Analyzers

When you run any dotnet ef command, the EF Core CLI builds your project internally. It does this to discover your DbContext class, entity types, and migration history. This internal build invokes the full MSBuild pipeline — including your Roslyn analyzers.

If your project has:

  • <TreatWarningsAsErrors>true</TreatWarningsAsErrors> in your .csproj
  • /warnaserror in your build arguments
  • Specific analyzer warnings promoted to errors with <WarningsAsErrors>CA2100;CS8600</WarningsAsErrors>

…then an analyzer warning during the EF internal build becomes a build error, and dotnet ef aborts the command.

This is particularly common when:

  • You’ve added a SAST analyzer NuGet package (SecurityCodeScan.VS2019, SonarAnalyzer.CSharp, or a third-party analyzer)
  • Your project targets .NET 8 with AnalysisLevel=latest-recommended which enables many new rules
  • You’ve recently upgraded analyzer packages and new rules now fire on your codebase
  • Your generated code (EF migration files themselves, scaffolded controllers) triggers analyzer warnings that you haven’t suppressed

The EF CLI analyzes the same code your application build analyzes — it just doesn’t need the security analysis to find a DbContext. That’s the core mismatch you’re resolving.


The Fix: Every Command Variant

The -- separator tells dotnet ef to pass all following arguments directly to MSBuild. Both /p: (Windows-style) and -p: (Unix/GNU-style) MSBuild property syntax work identically on all platforms.

dotnet ef migrations add

# Windows-style (works on Windows, Linux, macOS)
dotnet ef migrations add MyMigration -- /p:RunAnalyzersDuringBuild=false

# Unix-style short form (works on Windows, Linux, macOS)
dotnet ef migrations add MyMigration -- -p:RunAnalyzersDuringBuild=false

# With explicit project and startup project paths
dotnet ef migrations add MyMigration \
  --project src/DataAccess \
  --startup-project src/Api \
  -- /p:RunAnalyzersDuringBuild=false

# PowerShell — quote if the shell strips the slash
dotnet ef migrations add MyMigration -- "/p:RunAnalyzersDuringBuild=false"

dotnet ef database update

# Apply all pending migrations
dotnet ef database update -- /p:RunAnalyzersDuringBuild=false

# Apply migrations up to a specific migration name
dotnet ef database update TargetMigration -- /p:RunAnalyzersDuringBuild=false

# With project paths
dotnet ef database update \
  --project src/DataAccess \
  --startup-project src/Api \
  -- /p:RunAnalyzersDuringBuild=false

Also disabling code style enforcement

If your project also has <EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>, you may need to disable that separately:

dotnet ef database update \
  -- /p:RunAnalyzersDuringBuild=false /p:EnforceCodeStyleInBuild=false

Why -- Is Required

Without the -- separator, the EF CLI interprets /p:RunAnalyzersDuringBuild=false as an unknown dotnet ef argument and fails with an error like:

Unrecognized option '/p:RunAnalyzersDuringBuild=false'

The -- is an argument-separator convention: everything before -- belongs to dotnet ef; everything after -- is forwarded to the underlying MSBuild invocation. This is a standard EF Core CLI feature available in EF Core 5.0+ tooling.

If you see Error: unknown option '--', your dotnet-ef tool is out of date:

dotnet tool update --global dotnet-ef

Alternative: Configure the .csproj for Design-Time Builds

Instead of passing the flag on every command, conditionally disable analyzers in your .csproj for design-time builds:

<!-- .csproj — disable analyzers only during EF design-time builds -->
<PropertyGroup Condition="'$(DesignTimeBuild)' == 'true'">
  <RunAnalyzersDuringBuild>false</RunAnalyzersDuringBuild>
</PropertyGroup>

This disables Roslyn analyzer execution when Visual Studio tooling or dotnet ef triggers a design-time build, but leaves analyzers enabled for your regular dotnet build and CI pipeline builds.

A more targeted approach — only disable analyzers when a custom property is passed:

<!-- .csproj -->
<PropertyGroup Condition="'$(SkipAnalyzersForEF)' == 'true'">
  <RunAnalyzersDuringBuild>false</RunAnalyzersDuringBuild>
</PropertyGroup>

Then in your migration scripts:

dotnet ef database update -- /p:SkipAnalyzersForEF=true

And in your CI application build, SkipAnalyzersForEF is never set — analyzers run normally.


What NOT To Do

Do Not Set RunAnalyzersDuringBuild=false Globally

This is the most common mistake:

<!-- ⚠️ DO NOT DO THIS — disables ALL Roslyn analyzer runs globally -->
<PropertyGroup>
  <RunAnalyzersDuringBuild>false</RunAnalyzersDuringBuild>
</PropertyGroup>

Setting this unconditionally disables analyzers on every build — including your CI security scan build. If you’re using Roslyn security rules (CA2100 for SQL injection, CA3001CA3012 for various injection types, CA5350/CA5351 for weak cryptography), this configuration silently removes all of those checks from your pipeline.

The CI build log will show success with no analyzer warnings — because analyzers aren’t running. This is a false sense of security, not a solution.

Do Not Disable Analyzers in Your Main Build Step

# ⚠️ WRONG — disables security analysis on your application code
- name: Build
  run: dotnet build -- /p:RunAnalyzersDuringBuild=false

The /p:RunAnalyzersDuringBuild=false flag belongs only on dotnet ef commands — never on your main application build.


The Correct CI/CD Pattern

Here’s the pipeline structure that keeps security analysis on your application build while avoiding analyzer conflicts on EF migration commands:

GitHub Actions

name: Build, Analyze & Migrate

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  build-and-analyze:
    name: Build + Security Analysis
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup .NET
        uses: actions/setup-dotnet@v4
        with:
          dotnet-version: '8.x'

      - name: Restore
        run: dotnet restore

      # Analyzers run here — this is your security gate
      - name: Build with Roslyn Analyzers
        run: |
          dotnet build --configuration Release \
            /p:RunAnalyzersDuringBuild=true \
            /p:AnalysisLevel=latest-recommended \
            /warnaserror:CA2100,CA3001,CA3006,CA5350,CA5351

  migrate:
    name: Apply EF Migrations
    runs-on: ubuntu-latest
    needs: build-and-analyze
    if: github.ref == 'refs/heads/main'
    steps:
      - uses: actions/checkout@v4

      - name: Setup .NET
        uses: actions/setup-dotnet@v4
        with:
          dotnet-version: '8.x'

      - name: Install EF Tools
        run: dotnet tool install --global dotnet-ef

      # Analyzers disabled ONLY for the EF migration build
      - name: Apply Migrations
        run: |
          dotnet ef database update \
            --project src/DataAccess \
            --startup-project src/Api \
            -- /p:RunAnalyzersDuringBuild=false
        env:
          ConnectionStrings__Default: ${{ secrets.PROD_DB_CONNECTION }}

Key points:

  • The build-and-analyze job runs with analyzers fully enabled — this is your security gate
  • The migrate job only runs after a successful security-analyzed build (needs: build-and-analyze)
  • Analyzers are suppressed only in the EF migration step, not in the application build
  • Migrations only run on the main branch after the build passes

Azure DevOps

# azure-pipelines.yml
trigger:
  - main
  - develop

stages:
  - stage: Build
    jobs:
      - job: BuildAndAnalyze
        pool:
          vmImage: 'ubuntu-latest'
        steps:
          - task: UseDotNet@2
            inputs:
              version: '8.x'

          - script: dotnet restore
            displayName: Restore

          # Security-gated build with Roslyn analyzers
          - script: |
              dotnet build --configuration Release \
                /p:RunAnalyzersDuringBuild=true \
                /warnaserror:CA2100,CA3001,CA3006,CA5350,CA5351
            displayName: Build + Security Analysis

  - stage: Migrate
    dependsOn: Build
    condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
    jobs:
      - job: ApplyMigrations
        pool:
          vmImage: 'ubuntu-latest'
        steps:
          - script: dotnet tool install --global dotnet-ef
            displayName: Install EF Tools

          # EF migration build — analyzers disabled
          - script: |
              dotnet ef database update \
                --project src/DataAccess \
                --startup-project src/Api \
                -- /p:RunAnalyzersDuringBuild=false
            displayName: Apply EF Migrations
            env:
              ConnectionStrings__Default: $(ProdDbConnection)

Roslyn Security Rules That Commonly Block dotnet ef

When dotnet ef fails due to analyzer errors, these are the most common culprits — and what they detect:

RuleWhat It FlagsWhy EF Code Triggers It
CA2100SQL injection in SqlCommandRaw SQL in migration helper methods
CA3001CA3012Various injection patternsGenerated scaffolding code with raw queries
CA5369Insecure XmlSerializerAuto-generated serialization code
CA5394Non-cryptographic random usageMigration seed data using Random
CS8600CS8629Nullable reference warningsGenerated migration code in older projects
IDE0xxxCode style rulesGenerated migration class formatting

For CS warnings and IDE rules, the issue is usually that your migration files (which are auto-generated by dotnet ef) don’t conform to your project’s code style rules. In this case, suppressing analyzers for the EF build with -- /p:RunAnalyzersDuringBuild=false is the correct approach — not modifying the generated migration files to satisfy style rules.


Keeping Security Analysis Intact

Passing RunAnalyzersDuringBuild=false to dotnet ef commands is safe because:

  1. EF migration files themselves are not attack surfaces for injection vulnerabilities — they’re generated code that runs during deployment, not user-facing code that processes untrusted input
  2. Your application’s business logic, controller code, and data access layer are analyzed in your main build step, not the EF tool build
  3. The flag is applied surgically — only to the dotnet ef command, not to dotnet build

However, Roslyn analyzers have a fundamental limitation: they perform only intra-method analysis. An analyzer can detect SQL injection when a SqlCommand is built with string concatenation in the same method as the Request.QueryString read — but it cannot trace injection chains that span multiple methods, service layers, or class boundaries.

For deeper security coverage of your .NET codebase — including interprocedural taint analysis, second-order SQL injection detection, and stored XSS across request boundaries — a dedicated SAST platform is required alongside Roslyn analyzers. Offensive360 runs as a separate analysis step in your CI/CD pipeline and does not interact with RunAnalyzersDuringBuild at all.


Quick Reference

TaskCommand
migrations add (any platform)dotnet ef migrations add Name -- /p:RunAnalyzersDuringBuild=false
migrations add (Unix-style flag)dotnet ef migrations add Name -- -p:RunAnalyzersDuringBuild=false
database updatedotnet ef database update -- /p:RunAnalyzersDuringBuild=false
database update + style rulesdotnet ef database update -- /p:RunAnalyzersDuringBuild=false /p:EnforceCodeStyleInBuild=false
Disable only for design-timeAdd <Condition="'$(DesignTimeBuild)'=='true'"> to .csproj
Main app build (keep analyzers ON)dotnet build /p:RunAnalyzersDuringBuild=true

For the complete guide including all troubleshooting scenarios, Docker configuration, and the full CI/CD pipeline pattern, see: dotnet ef RunAnalyzersDuringBuild=false — Complete Guide.


Frequently Asked Questions

Does dotnet ef migrations add -- /p:RunAnalyzersDuringBuild=false work on Linux and macOS?

Yes. Both /p: and -p: property prefix styles work on Linux, macOS, and Windows in all modern .NET versions. The -- separator is available in EF Core 5.0+ tooling. If -- is not recognized, update: dotnet tool update --global dotnet-ef.

Will disabling analyzers for the EF build affect my migration files?

No. RunAnalyzersDuringBuild=false only affects the Roslyn analyzer execution during the EF tool’s internal project build. Your migration files are still generated with the same content. The flag has no effect on what migrations are created, how they’re structured, or how they’re applied to the database.

Why does dotnet ef succeed locally but fail in CI?

CI pipelines often have stricter build settings than local development. Common causes:

  • CI sets /warnaserror or TreatWarningsAsErrors=true globally — which your local build doesn’t have
  • CI uses a different .NET SDK version with additional analyzer rules enabled by default
  • CI restores different NuGet package versions including newer analyzer packages with new rules

Adding -- /p:RunAnalyzersDuringBuild=false to your CI EF migration steps resolves all of these.

Is RunAnalyzersDuringBuild the same as RunCodeAnalysis?

They control different things. RunAnalyzersDuringBuild controls whether Roslyn source analyzers (NuGet analyzer packages and built-in SDK analyzers) run during the build. RunCodeAnalysis controls the older FxCop-style static analysis. In modern .NET projects, RunAnalyzersDuringBuild=false is the relevant flag. If your project still uses legacy FxCop rules, you may need to set both.

What if the EF command still fails after adding the flag?

Check whether your project has <EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild> — this runs code style analysis (Roslyn analyzers for IDE0xxx rules) separately from RunAnalyzersDuringBuild. Pass both flags:

dotnet ef database update \
  -- /p:RunAnalyzersDuringBuild=false /p:EnforceCodeStyleInBuild=false

Also verify you’re using dotnet-ef 5.0 or later: dotnet ef --version.


For deep security analysis of your .NET codebase that goes beyond Roslyn analyzers — detecting second-order SQL injection, stored XSS, and complex taint flows — Offensive360 SAST integrates with your Azure DevOps, GitHub Actions, or Jenkins pipeline without interfering with your EF migration workflow. Run a one-time scan for $500 or book a demo.

Offensive360 Security Research Team

Application Security Research

Updated May 23, 2026

Find vulnerabilities before attackers do

Run Offensive360 SAST and DAST against your applications and get a full vulnerability report in minutes.