【问题标题】:C# & SQL Server query returning null columns on large tableC# & SQL Server 查询在大表上返回空列
【发布时间】:2017-12-28 06:39:27
【问题描述】:

我正在对一个大约有 600 列的表运行以下查询:

SELECT * 
FROM Table 
WHERE [Owner] = 1234

我正在使用 EF 代码优先和 Dapper 运行此查询,但我遇到了同样的问题。

特别是 DO 具有值的许多行从查询中返回为DBNull(我使用 SQL Server Management Studio 验证了这些列具有数据)。奇怪的是,它只在请求所有列时发生(无论是使用* 还是显式拉取它们)。

例如,如果列 Status 的值为 "A",则查询返回 DBNull 作为其值。但如果不是上面的代码(拉 600 列)我使用这个查询:

SELECT [Status] 
FROM Table 
WHERE [Owner] = 1234

Status 列已正确填充。

这是我用来处理结果的 Dapper 代码:

public IList<Dictionary<string, string>> GetData() {
    var sql = "SELECT * FROM Table WHERE [Owner] = 1234";
    var cn = new SqlConnection(serverConnectionString);
    var rows = new List<Dictionary<string, string>>();

    using (var reader = cn.ExecuteReader(sql))
    {
        while (reader.Read())
        {
            var dict = new Dictionary<string, string>();

            for (var i = 0; i < reader.FieldCount; i++)
            {
                var propName = reader.GetName(i).ToLowerInvariant();

                // This is set to DBNull for most, but not all,
                // columns if querying the ~600 columns in the Table
                var propValue = reader.GetValue(i); 

                dict[propName] = propValue?.ToString();
            }

            rows.Add(dict);
        }
    }

    return rows;
}

我无法对这种行为做出判断。任何帮助将不胜感激。

【问题讨论】:

  • 您可以尝试使用一些 order by 子句运行这两个查询,看看它是否给出相同的结果?
  • 顺便说一句,一个表中有 600 列是一种巨大的代码味道。
  • 有趣!可能是 dapper 的错误?直接使用 ADO.Net 时会出现相同的行为吗?我也会在我们的设置中做一些测试。
  • @Rob 我完全同意。我的团队正在将数据迁移到设计更合理的东西上。这就是为什么我需要从数据库中读取所有数据。
  • @Subbu 我已经使用了 Dapper 和 EF CodeFirst,并且都给出了相同的结果。我还没有直接使用过 ADO.Net

标签: c# .net sql-server .net-core dapper


【解决方案1】:

尝试使用 Dapper 的 .Query() 扩展来返回动态对象列表。下面是一个快速测试:

[Test]
public void Test_Large_Number_of_Columns()
{
    const int n = 600;
    var cols = "";

    for (var i = 0; i < n; i++)
    {
        cols += "col" + i + " varchar(50) null,";
    }

    var create = String.Format("IF OBJECT_ID('dbo.foo', 'U') IS NOT NULL DROP TABLE dbo.foo; create table foo({0})", cols);

    using (var conn = new SqlConnection(@"Data Source=.\sqlexpress;Integrated Security=true; Initial Catalog=foo"))
    {
        conn.Execute(create);

        conn.Execute("insert into foo(col300) values('hello') ");

        var result = conn.Query("select * from foo").AsList();

        Assert.That(result[0].col300, Is.EqualTo("hello"));

    }
} 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-21
    • 1970-01-01
    • 1970-01-01
    • 2014-01-09
    • 2011-01-17
    • 1970-01-01
    • 2012-02-19
    相关资源
    最近更新 更多