Невозможно преобразовать список, содержащий несколько классов в DataTable - PullRequest
1 голос
/ 06 марта 2019

Я пытаюсь преобразовать список в 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 ]

2 голосов
/ 06 марта 2019

Используйте ObjectReader FastMember для создания 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 создает объект, который оборачивает любую коллекцию и предоставляет его через интерфейс IDataReader, который можно использовать с SqlBulkCopy.

Также возможно использовать LinT-to-Dataset * CopyToDataTable или MoreLinq ToDataTable методы расширения для создания DataTable из IEnumerable.Они должны будут прочитать весь IEnumerable и кэшировать все данные в DataTable.Это может быть дорого, если есть много строк.

С другой стороны, ObjectReader ничего не нужно кэшировать

0 голосов
/ 07 марта 2019

Если вы можете читать данные в таблице данных, измените код, как показано ниже

bulkCopy.DestinationTableName = "dbo.Student";
bulkCopy.ColumnMappings.Add("<list field name>", "<database field name>");
//Map all your column as above
bulkCopy.WriteToServer(dataTable);

Надеюсь, это поможет вашей проблеме.

0 голосов
/ 06 марта 2019

Ошибка 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-not-match

...