You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用C# Core从数据库生成Dfs2文件的数据绑定问题排查

问题:Dfs2文件数据与Python生成版本不符,排查C#代码数据绑定问题

我从数据库获取了45列72行的数据,需要生成5列9行的Dfs2文件(72行对应72小时)。文件可以正常生成,但数据和之前用Python生成的正确Dfs2文件不一致,请帮忙排查我的C#代码中数据绑定是否存在问题。

我的C#代码

DataTable ecmwfWsData = new DataTable();
NpgsqlCommand cmd = new NpgsqlCommand(sqlSelectQuery, connection);
NpgsqlDataAdapter adp = new NpgsqlDataAdapter(cmd);
adp.Fill(ecmwfWsData);

string[] itemNames ={
    "ECMWFC0000Ctrl", "ECMWFC0001Ctrl", "ECMWFC0002Ctrl", "ECMWFC0003Ctrl", "ECMWFC0004Ctrl",
    "ECMWFC0100Ctrl", "ECMWFC0101Ctrl", "ECMWFC0102Ctrl", "ECMWFC0103Ctrl", "ECMWFC0104Ctrl",
    "ECMWFC0200Ctrl", "ECMWFC0201Ctrl", "ECMWFC0202Ctrl", "ECMWFC0203Ctrl", "ECMWFC0204Ctrl",
    "ECMWFC0300Ctrl", "ECMWFC0301Ctrl", "ECMWFC0302Ctrl", "ECMWFC0303Ctrl", "ECMWFC0304Ctrl",
    "ECMWFC0400Ctrl", "ECMWFC0401Ctrl", "ECMWFC0402Ctrl", "ECMWFC0403Ctrl", "ECMWFC0404Ctrl",
    "ECMWFC0500Ctrl", "ECMWFC0501Ctrl", "ECMWFC0502Ctrl", "ECMWFC0503Ctrl", "ECMWFC0504Ctrl",
    "ECMWFC0600Ctrl", "ECMWFC0601Ctrl", "ECMWFC0602Ctrl", "ECMWFC0603Ctrl", "ECMWFC0604Ctrl",
    "ECMWFC0700Ctrl", "ECMWFC0701Ctrl", "ECMWFC0702Ctrl", "ECMWFC0703Ctrl", "ECMWFC0704Ctrl",
    "ECMWFC0800Ctrl", "ECMWFC0801Ctrl", "ECMWFC0802Ctrl", "ECMWFC0803Ctrl", "ECMWFC0804Ctrl"
};

if (ecmwfWsData.Rows.Count == 0)
{
    return $"Data is not present for FRDate: {frDate} and FRun: {fRun}";
}
else
{
    double x0 = 79.89999974583402;
    double y0 = 12.500001526228607;
    string[] dfsCoordinate = { "LONG/LAT", x0.ToString(), y0.ToString(), "0" };
    double dfsDx = 0.1;
    double dfsDy = 0.1;
    int dfsDt = 3600;

    var fDTime = "";
    var frdate = $"{frDate.Substring(0, 4)}-{frDate.Substring(4, 2)}-{frDate.Substring(6, 2)}";
    DateTime date = Convert.ToDateTime(frdate);

    if (fRun.Equals("R00"))
    {
        fDTime = date.ToString("dd-MM-yyyy 06:30:00");
    }
    else if (fRun.Equals("R06"))
    {
        fDTime = date.ToString("dd-MM-yyyy 12:30:00");
    }
    else if (fRun.Equals("R12"))
    {
        fDTime = date.ToString("dd-MM-yyyy 18:30:00");
    }
    else if (fRun.Equals("R18"))
    {
        date = date.AddDays(1);
        fDTime = date.ToString("dd-MM-yyyy 00:30:00");
    }

    DateTime dfsstarttime = DateTime.ParseExact(fDTime, "dd-MM-yyyy HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture);
    double[,,] ecmwfGridData = new double[72, 9, 5];
    int ni = 0;

    foreach (DataRow row in ecmwfWsData.Rows)
    {
        int columnIndex = 0;
        for (int i = 0; i < 9; i++)
        {
            for (int j = 0; j < 5; j++)
            {
                ecmwfGridData[ni, i, j] = Math.Round((double)Convert.ToDouble(row.Field<float>(columnIndex)), 1);
                columnIndex++;
            }
        }
        ni++;
    }

    DfsFactory factory = new DfsFactory();
    Dfs2Builder builder = Dfs2Builder.Create("ECMWFGridData", "dfs Timeseries Bridge", 0);

    builder.SetDataType(1);
    builder.SetGeographicalProjection(factory.CreateProjectionGeoOrigin("UTM-33", 12.438741600559766, 55.225707842436385, 326.99999999999955));
    builder.SetTemporalAxis(factory.CreateTemporalEqCalendarAxis(eumUnit.eumUminute, dfsstarttime, 0, 60));
    builder.SetSpatialAxis(factory.CreateAxisEqD2(eumUnit.eumUmeter, ecmwfGridData.GetLength(2), 0, dfsDy, ecmwfGridData.GetLength(1), 0, dfsDx));
    builder.DeleteValueDouble = -1e-30;

    builder.AddCustomBlock(factory.CreateCustomBlock("M21_Misc", new double[] { 327, 0.2, -900, 10, 0, 0, 0 }));

    foreach (var item in itemNames)
    {
        builder.AddDynamicItem(item, eumQuantity.Create(eumItem.eumIRainfall, eumUnit.eumUmillimeter), DfsSimpleType.Double, DataValueType.Instantaneous);
    }

    string dfsfilename = Path.Combine($"D:\\DFS2", $"AllWSDFS_{frDate}_{fRun}_CtrlFile.dfs2");
    builder.CreateFile(dfsfilename);
    Dfs2File file = builder.GetFile();

    for (int i = 0; i < 72; i++)
    {
        for (int j = 0; j < itemNames.Length; j++)
        {
            IDfsItemData2D<double> itemData2D = (IDfsItemData2D<double>)file.CreateEmptyItemData(j + 1);

            double[,] transposedData = new double[ecmwfGridData.GetLength(2), ecmwfGridData.GetLength(1)];
            for (int k = 0; k < ecmwfGridData.GetLength(2); k++)
            {
                for (int l = 0; l < ecmwfGridData.GetLength(1); l++)
                {
                    transposedData[k, l] = ecmwfGridData[i, l, k];
                }
            }

            int totalElements = transposedData.GetLength(0) * transposedData.GetLength(1);
            double[] data = new double[totalElements];
            int index = 0;

            for (int k = 0; k < transposedData.GetLength(0); k++)
            {
                for (int l = 0; l < transposedData.GetLength(1); l++)
                {
                    data[index++] =  Math.Round(transposedData[k, l], 1);
                }
            }

            file.WriteItemTimeStep(j + 1, i, 60, data);
        }
    }
    file.Close();
}

核心排查点

  1. 数据填充的维度顺序
    你的ecmwfGridData是[72,9,5](时间步、行、列),数据库每行45列对应9*5的网格。需确认数据库的45列是否严格按「9组,每组5列」的顺序排列——如果实际是「5组,每组9列」,当前的i(行)外层、j(列)内层循环会直接导致行列数据错位。

  2. 数据写入的扁平化顺序错误
    Dfs2要求一维数据按**行优先(先遍历所有列,再换下一行)**排列,即顺序为[行0列0, 行0列1,...,行0列4,行1列0,...,行8列4]。但你当前的转置+扁平化逻辑是按列优先遍历,生成的顺序是[列0行0,列0行1,...,列0行8,列1行0,...,列4行8],这是数据错位的核心原因。

    修正方案:跳过转置步骤,直接按行优先顺序生成一维数组:

    int totalElements = 9 * 5;
    double[] data = new double[totalElements];
    int index = 0;
    for (int l = 0; l < 9; l++) // 先遍历行
    {
        for (int k = 0; k < 5; k++) // 再遍历列
        {
            data[index++] = Math.Round(ecmwfGridData[i, l, k], 1);
        }
    }
    
  3. 空间轴参数匹配
    CreateAxisEqD2的参数顺序是(单位, nx, x0, dx, ny, y0, dy),其中nx是列数、ny是行数。你当前用ecmwfGridData.GetLength(2)(5)作为nx,GetLength(1)(9)作为ny是正确的,但需确认Python版本是否用了完全一致的空间轴参数,否则会导致数据空间映射错误。

  4. 时间轴与时间步一致性
    确认Python版本的时间轴起始时间、步长和你的代码完全匹配——当前代码时间步长为60分钟,写入时传递的步长参数也是60,若Python版本用了不同的时间配置,会导致时间步对应的数据错位。

内容的提问来源于stack exchange,提问作者Sidhant Priyadarshan Biswal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 14:52:04