无法将列表转换为DataTable包含多个类

时间:2019-03-06 15:01:28

标签: c# sqlbulkcopy

我正在尝试将列表转换为dataTable,然后将其保存到数据库,但是我遇到了问题。我收到列映射不匹配的错误。

这是我的列表

public static class Program
{
    static Logger _myLogger = LogManager.GetCurrentClassLogger();

    public class Student
    {
        public int int { get; set; }
    public string name { get; set; }
    public string email { get; set; }
    public string phoneNumber { get; set; }
    public virtual ICollection<tblStudentCourses> tblStudentCourses { get; set; }
}

List<Student> student = new List<Student>();

这是我正在使用的扩展名

public static DataTable AsDataTable<T>(this IList<T> data)
{
    DataTable dataTable = new DataTable(typeof(T).Name);

    //Get all the properties
    PropertyInfo[] Props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
    foreach (PropertyInfo prop in Props)
    {
        //Defining type of data column gives proper data table 
        var type = (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>) ? Nullable.GetUnderlyingType(prop.PropertyType) : prop.PropertyType);
        //Setting column names as Property names
        dataTable.Columns.Add(prop.Name, type);
    }
    foreach (T item in data)
    {
        var values = new object[Props.Length];
        for (int i = 0; i < Props.Length; i++)
        {
            //inserting property values to datatable rows
            values[i] = Props[i].GetValue(item, null);
        }
        dataTable.Rows.Add(values);
    }
    //put a breakpoint here and check datatable
    return dataTable;
}

这就是我叫扩展名

 using (var connection = new SqlConnection(ConfigurationManager.AppSettings["connectionString"]))
            {
                connection.Open();
                SqlTransaction transaction = connection.BeginTransaction();

                using (var bulkCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.Default, transaction))
                {
                    bulkCopy.DestinationTableName = "dbo.Student";

                        bulkCopy.WriteToServer(student.AsDataTable());
    connection.Close();
                }

                transaction.Commit();
            }

错误:

给定的ColumnMapping与源或目标中的任何列都不匹配

3 个答案:

答案 0 :(得分:2)

使用FastMember's ObjectReader在任何集合的顶部创建IDataReader,例如:

var student = new List<Student>();
...
using(var bcp = new SqlBulkCopy(connection)) 
using(var reader = ObjectReader.Create(student, "Id", "Name", "Email","PhoneNumber")) 
{ 
    bcp.DestinationTableName = "SomeTable"; 
    bcp.WriteToServer(reader); 
}

SqlBulkCopy可以使用DataTable或IDataReader。 ObjectReader.Create创建一个包装所有集合的对象,并通过可与SqlBulkCopy一起使用的IDataReader接口公开它。

还可以使用Linq-to-Dataset的CopyToDataTable或MoreLinq的ToDataTable扩展方法从IEnumerable创建DataTable。这些将不得不读取整个IEnumerable,并将所有数据缓存在DataTable中。如果行很多,这可能会很昂贵。

另一方面,

ObjectReader不需要缓存任何内容

答案 1 :(得分:0)

错误The given ColumnMapping does not match up with any column in the source or destination

通常发生3种原因:

  • 您未提供任何ColumnMappings,并且源中的列多于目标中的列。
  • 您为源提供了无效的列名。
  • 您为目的地提供了无效的列名。

在您的情况下,您没有提供列映射。这是一个与您的情况类似的在线示例:https://dotnetfiddle.net/WaeUi9

要修复它:

  • 提供ColumnMappings

例如:https://dotnetfiddle.net/Zry2tb

有关此错误的更多信息,请参见:https://sqlbulkcopy-tutorial.net/columnmapping-does-not-match

答案 2 :(得分:0)

如果您能够读取数据表中的数据,请按如下所示更改代码

#include <iostream>
class NGramFST{
private:
    static NGramFST* m_Instace;

public:
    NGramFST(){
    }

    static NGramFST* getInstance() {
        if (m_Instace == NULL){
            m_Instace = new NGramFST();
        }
        return m_Instace;
    }

    double getProbabilityOfWord(std::string word, std::string context) {
        std::cout << "reloading..." << std::endl;
        return 1;
    }

};

我希望这能解决您的问题。