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

SqlDataReader执行查询报Invalid object name无效对象名异常

问题背景

服务逻辑为从公开API拉取文章数据,和数据库已有数据做去重校验后入库,报错在SqlDataReader初始化读取表数据时触发,相同的数据库查询代码在ASP.NET项目中运行无异常。

问题代码片段:

List<Thumbnail> Thumbnails = new List<Thumbnail>();

var client = new HttpClient
{
    BaseAddress = new Uri("https://api.spaceflightnewsapi.net/v3/articles?_limit=100")
};
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync(client.BaseAddress);
if (response.IsSuccessStatusCode)
{
    Thumbnails = JsonConvert.DeserializeObject<List<Thumbnail>>(response.Content.ReadAsStringAsync().Result);
}

if (Thumbnails != null)
{
    for (int i = 0; i < Thumbnails.Count; i++)
    {
        Thumbnails[i].PublishedAt = Thumbnails[i].PublishedAt.ToUniversalTime();
    }

    SqlConnection conn = new SqlConnection(connectionString);
    conn.Open();
    SqlCommand cmdr = new SqlCommand("SELECT * FROM mobilesdb.dbo.thumbnails ORDER BY PublishedAt", conn)
    {
        CommandType = CommandType.Text
    };
    SqlDataReader reader = await cmdr.ExecuteReaderAsync();//error: System.Data.SqlClient.SqlException: 'Invalid object name 'mobilesdb.dbo.thumbnails'.'

    try
    {
        while (reader.Read())
        {
            Thumbnail thumbnail = new Thumbnail()
            {
                Title = reader.GetString(1),
                Url = reader.GetString(2),
                ImageUrl = reader.GetString(3),
                NewsSite = reader.GetString(4),
                Summary = reader.GetString(5),
                PublishedAt = reader.GetDateTime(reader.GetOrdinal(nameof(thumbnail.PublishedAt))),
                UpdatedAt = reader.GetDateTime(reader.GetOrdinal(nameof(thumbnail.UpdatedAt))),
            };

            for (int i = 0; i < Thumbnails.Count; i++)
            {
                if (Thumbnails[i].Title.Equals(thumbnail.Title) &&
                    Thumbnails[i].NewsSite.Equals(thumbnail.NewsSite) &&
                    Thumbnails[i].Summary.Equals(thumbnail.Summary))
                {
                    Thumbnails.RemoveAt(i);
                }
            }
        }
    }
    catch (Exception) { }

    reader.Close();

报错附加信息:

Exception thrown: 'System.Data.SqlClient.SqlException' in mscorlib.dll An exception of type 'System.Data.SqlClient.SqlException' occurred in mscorlib.dll but was not handled in user code Invalid object name 'thumbnails'.


根因分析

不要因为同一段SQL在其他项目能跑就排除连接/对象存在性问题,90%的这类报错都是以下原因导致:

  • 核心问题:当前服务的数据库连接指向的实例/库中,不存在mobilesdb.dbo.thumbnails这张表
    • 核对当前项目的connectionString配置和正常运行的ASP.NET项目是否完全一致,常见坑点:不同项目用了独立的LocalDB实例、配置文件变换(Debug/Release)切到了测试库、连接地址/实例名写错连到了其他SQL Server实例,这些场景下目标实例里根本没有建过这张表
    • 检查连接账号权限:如果账号对mobilesdb库没有访问权限,SQL Server不会明确返回权限不足,而是直接抛出"无效对象名"的错误
    • 检查对象名拼写:确认库名、schema名、表名的拼写和实际一致,注意SQL Server默认实例排序规则不区分大小写,但部分自定义实例会开启大小写敏感,拼写偏差会直接报表不存在
  • 代码附带的隐患(和当前报错无关但会引发其他线上问题):
    • 遍历Thumbnails列表时直接调用RemoveAt(i)删除元素,会导致集合索引错位,漏判重复项甚至触发索引越界
    • SqlConnection/SqlCommand/SqlDataReader没有用using包裹,存在数据库连接泄露风险
    • 空catch块直接吞掉所有异常,出现问题时无法定位根因
    • 异步方法调用.Result取结果,在ASP.NET这类带同步上下文的环境下极易触发死锁
    • ExecuteReaderAsync放在try块外面,抛出的数据库异常完全不会被捕获

修复方案
  1. 先验证连接正确性:临时加测试语句执行SELECT DB_NAME(), @@SERVERNAME,确认当前连接的实例名、数据库名和预期一致,再执行SELECT * FROM mobilesdb.sys.tables WHERE name = 'thumbnails'确认表存在
  2. 对齐两个项目的数据库连接字符串,确认账号权限满足库表访问要求
  3. 修正代码逻辑问题,参考实现:
List<Thumbnail> Thumbnails = new List<Thumbnail>();

var client = new HttpClient
{
    BaseAddress = new Uri("https://api.spaceflightnewsapi.net/v3/articles?_limit=100")
};
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync(client.BaseAddress);
if (response.IsSuccessStatusCode)
{
    // 替换.Result为await避免死锁
    string respContent = await response.Content.ReadAsStringAsync();
    Thumbnails = JsonConvert.DeserializeObject<List<Thumbnail>>(respContent);
}

if (Thumbnails != null)
{
    // 统一转UTC时间
    for (int i = 0; i < Thumbnails.Count; i++)
    {
        Thumbnails[i].PublishedAt = Thumbnails[i].PublishedAt.ToUniversalTime();
    }

    // using包裹数据库对象,自动释放资源
    await using SqlConnection conn = new SqlConnection(connectionString);
    await conn.OpenAsync();
    SqlCommand cmdr = new SqlCommand("SELECT * FROM mobilesdb.dbo.thumbnails ORDER BY PublishedAt", conn)
    {
        CommandType = CommandType.Text
    };
    await using SqlDataReader reader = await cmdr.ExecuteReaderAsync();

    // 先把已有数据的唯一标识存入HashSet,避免边遍历边删列表导致的索引错位
    HashSet<(string title, string newsSite, string summary)> existedRecords = new();
    while (await reader.ReadAsync())
    {
        Thumbnail thumbnail = new Thumbnail()
        {
            Title = reader.GetString(1),
            Url = reader.GetString(2),
            ImageUrl = reader.GetString(3),
            NewsSite = reader.GetString(4),
            Summary = reader.GetString(5),
            PublishedAt = reader.GetDateTime(reader.GetOrdinal(nameof(Thumbnail.PublishedAt))),
            UpdatedAt = reader.GetDateTime(reader.GetOrdinal(nameof(Thumbnail.UpdatedAt))),
        };
        existedRecords.Add((thumbnail.Title, thumbnail.NewsSite, thumbnail.Summary));
    }

    // 批量移除重复项
    Thumbnails.RemoveAll(t => existedRecords.Contains((t.Title, t.NewsSite, t.Summary)));
    
    // 后续入库逻辑...
}
  1. 删除空catch块,所有异常必须记录日志,禁止直接吞错。

内容的提问来源于stack exchange,提问作者needlide

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 12:48:19