首页 > 解决方案 > C# SQL BulkCopy 日期时间插入问题

问题描述

我在将包含 C#DateTime对象的数据表批量插入 SQL Server 数据库时遇到问题,并且不断收到以下错误:

数据源中字符串类型的给定值无法转换为指定目标列的日期时间类型

我运行堆栈跟踪以查看表试图插入的内容(下图)

数据表插入

这是我用来解析日期的代码

 SInstance s = new SInstance {                    
                Timestamp = DateTime.ParseExact(values[0],"yyyy-MM-dd",null),
               //other property initializations                   
            };

在哪里

values[0] = "2018-08-08"

大多数其他答案都说要使用适当的格式手动配置数据表,但是这些表是在运行时使用类属性动态生成的,因此对任何内容进行硬编码都是不可能的。这是批量复制代码段的代码

DataTable dt = DBOHelper.GenerateDataTable(dbObjects);

using (SqlBulkCopy sqlBulk = _database.BulkCopySQL())
{
    sqlBulk.DestinationTableName = table;
    sqlBulk.BatchSize = commitBatchSize;

    try
    {
        sqlBulk.WriteToServer(dt);
        dt.Dispose();
    }
    catch (Exception e)
    {
        AuditEngine.Instance.LogError("DatabaseEngine", "SQLBulkInsert", e.Message);
        return 0;
    }
}

和表格生成器功能:

public static DataTable GenerateDataTable<T>(DBOCollection<T> dBOCollection)
        where T : DbObject
{
    DataTable dt = GenerateEmptyDataTable<T>();

    List<PropertyInfo> props = GetDBODataMemberProperties<T>();

    foreach (DbObject dbo in dBOCollection)
    {
        DataRow row = dt.NewRow();

        for (int i = 0; i < props.Count; i++)
        {
            row[i] = props[i].GetValue(dbo);
        }

        dt.Rows.Add(row);
    }

    return dt;
}

public static DataTable GenerateEmptyDataTable<T>()
        where T : DbObject
{
    DataTable dt = new DataTable();

    List<PropertyInfo> properties = GetDBODataMemberProperties<T>();

    foreach (PropertyInfo p in properties)
    {              
        dt.Columns.Add(p.Name, p.PropertyType);
    }

    return dt;
}

对于没有日期字段的对象,一切正常,但由于某种原因,我尝试过的所有日期格式都会引发错误。在此先感谢您的任何建议。

标签: c#sql-serverdatetimesqlbulkcopy

解决方案


答案是在运行时生成一个属性名称列表,然后将它们映射到 SqlBulkCopy 对象(这仅在数据库列名称和属性名称匹配时才有效)

DataTable dt = DBOHelper.GenerateDataTable(dbObjects, out List<string> propertyNames);

        using (SqlBulkCopy sqlBulk = _database.BulkCopySQL())
        {
            sqlBulk.DestinationTableName = table;
            sqlBulk.BatchSize = commitBatchSize;

            foreach (string s in propertyNames)
            {
                sqlBulk.ColumnMappings.Add(new SqlBulkCopyColumnMapping(s, s));
            }

            try
            {
                sqlBulk.WriteToServer(dt);
                dt.Dispose();
            }
            catch (Exception e)
            {
                AuditEngine.Instance.LogError("DatabaseEngine", "SQLBulkInsert", e.Message);
                return 0;
            }
        }

推荐阅读