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

C#控制台程序导入API XML数据至SQL Server失败,求解决

问题分析与解决方案

核心错误点

  • 空引用异常:代码中Person person = null;从未被赋值,直接使用person.ID等属性会抛出空引用异常,导致插入逻辑根本无法执行。
  • 未遍历API返回的数组:API返回的是Person[]数组,代码没有循环遍历数组中的每个对象,只尝试插入一条(还是null的)数据。
  • 连接释放重复操作:外层using (SqlConnection con)已经会自动管理连接的打开和关闭,嵌套的using (con)和手动con.Close()属于冗余操作,可能导致连接提前释放。
  • 无异常捕获:执行过程中出现错误时没有任何提示,无法定位问题。
  • 单条插入性能低下:1万条数据单条插入会大幅消耗数据库资源,效率极低。
  • XML反序列化潜在问题:ReadAsAsync<Person[]>默认依赖JSON格式化器,若API返回纯XML,可能无法正确反序列化为Person数组。

修正后的代码(直接批量入库版本)

控制台程序代码

using System;
using System.Configuration;
using System.Data.SqlClient;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Threading.Tasks;

class Program
{
    static void Main(string[] args)
    {
        try
        {
            var importTask = ImportApiDataToSql();
            importTask.Wait();
            Console.WriteLine("数据导入完成");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"导入失败:{ex.Message}");
            Console.WriteLine($"详细错误:{ex.InnerException?.Message}");
        }
        Console.ReadKey();
    }

    static async Task ImportApiDataToSql()
    {
        using (HttpClient client = new HttpClient())
        {
            Console.WriteLine("调用API中...");
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));

            var response = await client.GetAsync("http://localhost/webapi/api/user");
            response.EnsureSuccessStatusCode();

            // 反序列化XML到Person数组(显式指定XML格式化器)
            var persons = await response.Content.ReadAsAsync<Person[]>(new[] { new XmlMediaTypeFormatter() });
            Console.WriteLine($"API返回 {persons.Length} 条记录");

            // 使用SqlBulkCopy批量插入,提升大数量数据处理性能
            using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConnection"].ConnectionString))
            {
                await con.OpenAsync();
                using (SqlBulkCopy bulkCopy = new SqlBulkCopy(con))
                {
                    bulkCopy.DestinationTableName = "tblPerson";
                    // 映射实体属性与数据库列名
                    bulkCopy.ColumnMappings.Add("ID", "ID");
                    bulkCopy.ColumnMappings.Add("Name", "Name");
                    bulkCopy.ColumnMappings.Add("Mobile", "Mobile");
                    bulkCopy.ColumnMappings.Add("Birthday", "Birthday");

                    await bulkCopy.WriteToServerAsync(persons.ToDataTable());
                }
            }
        }
    }
}

// 辅助方法:将泛型集合转换为DataTable,适配SqlBulkCopy
public static class CollectionExtensions
{
    public static System.Data.DataTable ToDataTable<T>(this System.Collections.Generic.IEnumerable<T> items)
    {
        var dataTable = new System.Data.DataTable(typeof(T).Name);
        var properties = typeof(T).GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
        
        foreach (var prop in properties)
        {
            dataTable.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
        }
        
        foreach (var item in items)
        {
            var values = new object[properties.Length];
            for (int i = 0; i < properties.Length; i++)
            {
                values[i] = properties[i].GetValue(item) ?? DBNull.Value;
            }
            dataTable.Rows.Add(values);
        }
        
        return dataTable;
    }
}

实体类代码(保持不变)

public class Person
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Mobile { get; set; }
    public DateTime Birthday { get; set; }
}

存储为XML字符串入库的替代方案

如果需要将API返回的XML直接存储为字符串,可修改API数据获取与插入逻辑:

// 获取原始XML字符串
string xmlContent = await response.Content.ReadAsStringAsync();

// 插入到数据库(假设表存在XmlContent列,类型为nvarchar(max)或xml)
using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConnection"].ConnectionString))
{
    await con.OpenAsync();
    string sql = "INSERT INTO tblPersonXml (XmlContent) VALUES (@xmlContent)";
    using (SqlCommand cmd = new SqlCommand(sql, con))
    {
        cmd.Parameters.AddWithValue("@xmlContent", xmlContent);
        await cmd.ExecuteNonQueryAsync();
    }
}

关键优化说明

  1. 异步编程改进:使用async/await替代Wait(),避免线程阻塞,提升程序响应性。
  2. 批量插入:使用SqlBulkCopy处理大量数据,比单条插入效率提升数十倍。
  3. 异常捕获:添加全局异常捕获,输出错误信息方便排查问题。
  4. XML反序列化修正:显式指定XmlMediaTypeFormatter,确保XML数据能正确反序列化为实体数组。
  5. 连接管理:通过using语句自动管理数据库连接,避免连接泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 11:40:31