Member 12586110 Ответов: 1

C# создание datatable из списка


I am working on re-writing my code to use SqlBulkCopy Class to test the insert record performance. I am running into errors converting List to a DataTable.


public string toTbl(IList < string > records) {
    const string connectionString = @ "Data Source=sqlserver;Initial Catalog=dbname;User Id=user;Password=password;";    
    try {
        var studentData = from record in records
        let srec = record.Split(',')
        select new Student {
            ID = srec[0],
            Student = srec[1],
            Grade = srec[2]
        };

        foreach(var i in studentData) {
            using(SqlConnection sqlConnection = new SqlConnection(connectionString)) {
                sqlConnection.Open();    
                using(SqlCommand cmd = new SqlCommand("INSERT INTO [Student] ([ID], [Student], [Grade]) VALUES (@ID, @Student, @Grade)", sqlConnection)) {
                    cmd.Parameters.AddWithValue("@ID", i.ID);
                    cmd.Parameters.AddWithValue("@Student", i.Student);
                    cmd.Parameters.AddWithValue("@Grade", i.Grade);    
                    cmd.ExecuteNonQuery();
                }
                sqlConnection.Close();
            }
        }
    } catch (Exception ex) {
        message = ex.Message;
    }
}


Что я уже пробовал:

Я пишу этот код ниже и сталкиваюсь с ошибками. Не могли бы вы меня проводить?
Спасибо

private string toTbl(IList < string > records)
        {
            const string connectionString = @ "Data Source=sqlserver;Initial Catalog=dbname;User Id=user;Password=password;"; 
            try
            {               
                ListtoDataTable lsttodt = new ListtoDataTable();
                DataTable dt = lsttodt.ToDataTable(records);

                using (var conn = new SqlConnection(connectionString))
                {
                    await conn.OpenAsync();
                    using (var bulkCopy = new SqlBulkCopy(conn))
                    {
                        bulkCopy.DestinationTableName = "Student";

                        try
                        {
                            // Write from the source to the destination.
                            await bulkCopy.WriteToServerAsync(dt);
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            return (null);
        }

        public class ListtoDataTable
        {
            public DataTable ToDataTable<T>(List<T> items)
            {
                DataTable dataTable = new DataTable(typeof(T).Name);
                //Get all the properties by using reflection   
                PropertyInfo[] Props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
                foreach (PropertyInfo prop in Props)
                {
                    //Setting column names as Property names  
                    dataTable.Columns.Add(prop.Name);
                }
                foreach (T item in items)
                {
                    var values = new object[Props.Length];
                    for (int i = 0; i < Props.Length; i++)
                    {

                        values[i] = Props[i].GetValue(item, null);
                    }
                    dataTable.Rows.Add(values);
                }

                return dataTable;
            }
        }

j snooze

возможно, вы захотите опубликовать сообщение об ошибке и строку, в которой оно появляется при отладке.

Member 12586110

Привет, я получаю две ошибки по одной в DataTable dt = lsttodt.ToDataTable(records); и другие в await (await conn.OpenAsync();, await bulkCopy.WriteToServerAsync(dt);)

Ошибка: CS0411, аргументы типа для метода 'ListtoDataTable.ToDataTable<t>(List<t>)' не может быть выведен из использования. Попробуйте явно указать аргументы типа.
Ошибка: CS4032, оператор 'await' может использоваться только в асинхронном методе. Подумайте о том, чтобы пометить этот метод модификатором 'async' и изменить его возвращаемый тип на 'Task<string>'.

Спасибо

Maciej Los

Как по мне, класс ListToDataTable должен быть статическим, и его метод Todatable тоже. С другой стороны, ваши данные хранятся в List<string>, Что означает, что вы можете просто переписать их в DataTable:
DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn("Record", typeof(string)));
foreach(string item in records)
{
dt.Rows.Add(new object[]{item});
}

1 Ответов

Рейтинг:
6

Maciej Los

Прежде всего: Вы должны работать с данными, а не со строкой!
Что это значит?
Примечание: данные учащихся должны храниться в List<Student> вместо List<string>! Вы должны передать его в свой метод для массового копирования данных.

Во вторых: ListToDataTable класс должен быть статическим и его метод ToDataTable тоже!

public static class ListToDataTable
{
    public static DataTable ToDataTable<T>(List<T> items)
    {
     //body of method
    }
}


В-третьих, все: Если вы хотите использовать асинхронный метод, вам нужно будет создать асинхронный метод, который принимает список студентов, преобразованных в datatable. Подробнее на сайте: c# - асинхронность для массового копирования - переполнение стека[^]


Member 12586110

Привет, я написал ниже в соответствии с вашими вводными данными, но у меня есть 2 проблемы.

1) Как разделить мою строку, поскольку данные разделены запятыми, приведенный ниже код записывает все записи в поле ID.
2) не могли бы вы рассказать мне, как сделать вставки таблицы асинхронными, я буду вызывать toTbl() из другого метода.


	public string toTbl(IList < string > records)
        {
            const string connectionString = @"Data Source=dbsvr;Initial Catalog=dbname;User Id=usr;Password=pwd;";

            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn("ID", typeof(string)));
            dt.Columns.Add(new DataColumn("Student", typeof(string)));
            dt.Columns.Add(new DataColumn("Grade", typeof(string)));
            foreach (string item in records.Skip(1))
            {
                dt.Rows.Add(new object[] { item });
            }

            using (var conn = new SqlConnection(connectionString))
            {
                conn.Open();
                using (SqlBulkCopy s = new SqlBulkCopy(conn))
                {
                    s.DestinationTableName = "Student";
                    s.BatchSize = dt.Rows.Count;
                    s.BulkCopyTimeout = 0;
                    s.ColumnMappings.Add("ID", "ID");
                    s.ColumnMappings.Add("Student", "Student");
                    s.ColumnMappings.Add("Grade", "Grade");
                    s.WriteToServer(dt);
                    s.Close();
                }
                conn.Close();
            }
        }
			
    


Спасибо

Maciej Los

Похоже, вы знаете, как разбить строку на данные студента:
var studentData = from record in records
let srec = record.Split(',')
select new Student {
ID = srec[0],
Student = srec[1],
Grade = srec[2]

Что касается вопроса № 2: Пожалуйста, прочтите мой ответ еще раз.