我有一个对象类,我将其转换为List。我想将类转换为列表,因此我可以执行SQLBulkCopy,因为我当前的方法需要很长时间才能在SQL数据库表中编写数据。
class ExtractedInfo
{
public string Date { get; set; }
public string Client { get; set; }
public string Path { get; set; }
}
List<ExtractedInfo> extractedList = new List<ExtractedInfo>();
try
{
Console.WriteLine("Writing to DB");
using (SqlConnection conn = new SqlConnection(connectionStringPMT))
{
conn.Open();
SqlCommand cmd =
new SqlCommand(
"IF NOT EXISTS (SELECT 1 FROM [FileTrckT] WHERE Path = @Path) " +
"INSERT INTO [FileTrckT] (Date, Client, Path, DateAddedToDb, FileName) " + // dont forget to add "DateAddedToDb" on live code
"VALUES (@Date, @Client, @Path, @DateAddedToDb, @FileName)");// dont forget to add " @DateAddedToDb" on live code
cmd.CommandType = CommandType.Text;
cmd.Connection = conn;
cmd.Parameters.Add("@Date", DbType.DateTime);
cmd.Parameters.Add("@Client", DbType.String);
cmd.Parameters.Add("@Path", DbType.String);
cmd.Parameters.Add(@"DateAddedToDb",DbType.DateTime); //uncomment on live code
cmd.Parameters.Add("@FileName", DbType.String);
foreach (var extractedRecord in extractedList)
{
cmd.Parameters[0].Value = extractedRecord.Date;
cmd.Parameters[1].Value = extractedRecord.Client;
cmd.Parameters[2].Value = extractedRecord.Path;
cmd.Parameters[3].Value = DateTime.Now; //uncomment on live code
cmd.Parameters[4].Value = extractedRecord.Path.Substring(extractedRecord.Path.LastIndexOf("/")+1);
cmd.ExecuteNonQuery();
}
conn.Close();
}
} catch(Exception ex)
{
Console.WriteLine(ex.Message.ToString());
Console.WriteLine("Error occured whilst inserting data into sql table FiletrckT");
log.Info("Error occured whilst inserting data into sql table FiletrckT");
log.Error(DateTime.Now + ": " + ex.Message.ToString());
}
}
catch(Exception ex)
{
log.Error(DateTime.Now.ToString() + " " + ex.Message.ToString());
Console.WriteLine(ex.Message);
}
}
答案 0 :(得分:3)
更好的选择是使用FastMember's ObjectReader在集合或IEnumerable之上创建IDataReader。这样,您可以通过将所有内容复制到DataTable中来避免将内存使用量增加一倍。
来自回购的样本:
using(var bcp = new SqlBulkCopy(connection))
using(var reader = ObjectReader.Create(myList, "Id", "Name", "Description"))
{
bcp.DestinationTableName = "SomeTable";
bcp.WriteToServer(reader);
}
如果要导出所有字段,则无需传递字段列表。
该库可用through NuGet
如果您出于其他原因想要创建DataTable,可以使用MoreLINQ的ToDataTable。它与ToList
或ToArray
的工作方式相同,但会生成DataTable。完整的MoreLINQ库可通过NuGet获得。单个扩展名可用作代码包,例如ToDataTable的源代码为available here
<强>更新强>
ExtractedInfo
类似乎与FileTrckT
表的字段不匹配。这可以通过添加Select
调用来修复,该调用将ExtractedInfo
对象转换为表格所期望的形式,例如:
var itemsToAdd= from it in extractedList
select new { Date= DateTime.Parse(it.Date), //Or ParseExact
it.Client,
it.Path,
DateAddedToDb = DateTime.Now,
FileName = it.Path.Substring(it.Path.LastIndexOf("/")+1)
};
var fields=new []{"Date", "Client", "Path","DateAddedToDb","FileName"};
using(var bcp = new SqlBulkCopy(connection))
using(var reader = ObjectReader.Create(itemsToAdd, fields))
{
bcp.DestinationTableName = "FileTrckT";
bcp.WriteToServer(reader);
}
答案 1 :(得分:0)
您可以编写自己的通用转换方法,例如:
private DataTable ConvertToDatatable<T>(IList<T> data)
{
var props = TypeDescriptor.GetProperties(typeof(T));
DataTable table = new DataTable();
foreach (PropertyDescriptor prop in props)
table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
foreach (T item in data)
{
DataRow row = table.NewRow();
foreach (PropertyDescriptor prop in props)
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
table.Rows.Add(row);
}
return table;
}
或扩展方法:
static class MyExtenstions
{
public static DataTable ToDataTable<T>(this IList<T> data)
{
var props = TypeDescriptor.GetProperties(typeof(T));
DataTable table = new DataTable();
foreach (PropertyDescriptor prop in props)
table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
foreach (T item in data)
{
DataRow row = table.NewRow();
foreach (PropertyDescriptor prop in props)
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
table.Rows.Add(row);
}
return table;
}
}