Numeric storage parameters are formatted with the current culture, so migrations emit 0,01 instead of 0.01

オープン
#4,114 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

@Sorbitol がすでに取り組んでいます。

2026年10月29日 から。

  • #4115 @Sorbitol による — オープン

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
30/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
停滞
技術スタック
csharp, postgresql
領域
databases

調査の方向性

Start in src/EFCore.PG/Migrations/NpgsqlMigrationsSqlGenerator.cs, at GetStorageParameters, where non-boolean and non-string values are formatted. Check the migration SQL generator tests for storage parameters and add coverage for a decimal value under a comma-decimal culture. Done means generated CREATE TABLE, CREATE INDEX, and ALTER TABLE storage parameter SQL uses a dot decimal separator; pull request #4115 is already open.

索引モデルが issue の本文から書いたものです。

説明

Description

A non-integer numeric storage parameter (double, float, decimal) is written into DDL with the current culture's decimal separator. Under sv-SE, de-DE, fr-FR and other comma cultures, HasStorageParameter("autovacuum_vacuum_scale_factor", 0.01) generates autovacuum_vacuum_scale_factor=0,01, which breaks CREATE TABLE … WITH (…) and ALTER TABLE … SET (…) (and CREATE INDEX … WITH (…), which shares the same helper): the statement fails with a syntax error.

Model Culture Generated SQL
HasStorageParameter("autovacuum_vacuum_scale_factor", 0.01) en-US …(autovacuum_vacuum_scale_factor=0.01) ✅
same sv-SE …(autovacuum_vacuum_scale_factor=0,01) ❌
Environment
  • PostgreSQL 18.6 (only to confirm the error; the repro itself needs no database)
  • .NET SDK 10.0.403 / runtime 10.0.14, Npgsql.EntityFrameworkCore.PostgreSQL 10.0.3, EF Core 10.0.4, Npgsql 10.0.3
  • Windows 11, current culture sv-SE
Repro
using System.Globalization;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;

foreach (var culture in new[] { "en-US", "sv-SE" })
{
    CultureInfo.CurrentCulture = new CultureInfo(culture);
    Console.WriteLine($"--- {culture} ---");

    using var context = new TestContext();
    var generator = context.GetService<IMigrationsSqlGenerator>();
    var differ = context.GetService<IMigrationsModelDiffer>();
    var model = context.GetService<IDesignTimeModel>().Model.GetRelationalModel();

    var operations = differ.GetDifferences(null, model);
    foreach (var command in generator.Generate(operations, context.Model))
        Console.WriteLine(command.CommandText);
}

public class TestContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder options)
        => options.UseNpgsql("Host=unused");

    protected override void OnModelCreating(ModelBuilder modelBuilder)
        => modelBuilder.Entity<Row>().HasStorageParameter("autovacuum_vacuum_scale_factor", 0.01);
}

public class Row
{
    public int Id { get; set; }
}

Output (Npgsql.EntityFrameworkCore.PostgreSQL 10.0.3):

--- en-US ---
CREATE TABLE "Row" (
    "Id" integer GENERATED BY DEFAULT AS IDENTITY,
    CONSTRAINT "PK_Row" PRIMARY KEY ("Id")
)
WITH (autovacuum_vacuum_scale_factor=0.01);

--- sv-SE ---
CREATE TABLE "Row" (
    "Id" integer GENERATED BY DEFAULT AS IDENTITY,
    CONSTRAINT "PK_Row" PRIMARY KEY ("Id")
)
WITH (autovacuum_vacuum_scale_factor=0,01);

Diffing a model with 0.2 against one with 0.01 gives, under sv-SE: ALTER TABLE "Row" SET (autovacuum_vacuum_scale_factor=0,01); (en-US: =0.01). de-DE and fr-FR produce the same 0,01.

PostgreSQL 18 rejects the sv-SE statement:

ERROR:  syntax error at or near "01"
LINE 5: WITH (autovacuum_vacuum_scale_factor=0,01);
                                               ^
Source reference

GetStorageParameters formats every value other than bool and string with a plain ToString():

https://github.com/npgsql/efcore.pg/blob/cd8b7f9ac6e37deb2bd7ea18d318b6c25fd1b5c1/src/EFCore.PG/Migrations/NpgsqlMigrationsSqlGenerator.cs#L2280-L2290

Its result is used by WITH (…) (emitted for both CREATE TABLE and CREATE INDEX) and by ALTER TABLE … SET (…), while other numeric DDL in the same file already uses CultureInfo.InvariantCulture (RESTART WITH, INCREMENT BY). A likely fix is Convert.ToString(a.Value, CultureInfo.InvariantCulture)! on line 2289.

(Links are to main; the code is identical in v10.0.3, L2066–L2075, and still present on hotfix/10.0.4.)

Similar to #787 (invariant culture for DateTime literals).

Workaround: pass the value as a string ("0.01"), which the generator quotes and PostgreSQL accepts.

主要言語
C#
スター
1.8k
フォーク
268
平均マージ
2時間 35分
マージ済み PR(30日)
136

環境構築

このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

npgsql/efcore.pg のほかの issue

npgsql/efcore.pg の issue をすべて見る

似ている issue

C# の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。