为了在数据库中插入大量数据,我习惯于将所有插入信息收集到一个列表中,并将该列表转换为DataTable
。然后我通过SqlBulkCopy
将该列表插入到数据库中。
我将生成的列表发送到何处
LiMyList
其中包含要插入到数据库中的所有批量数据的信息
并将其传递给我的批量插入操作
InsertData(LiMyList, "MyTable");
InsertData
在哪里
public static void InsertData<T>(List<T> list,string TableName)
{
DataTable dt = new DataTable("MyTable");
clsBulkOperation blk = new clsBulkOperation();
dt = ConvertToDataTable(list);
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal);
using (SqlBulkCopy bulkcopy = new SqlBulkCopy(ConfigurationManager.ConnectionStrings["SchoolSoulDataEntitiesForReport"].ConnectionString))
{
bulkcopy.BulkCopyTimeout = 660;
bulkcopy.DestinationTableName = TableName;
bulkcopy.WriteToServer(dt);
}
}
public static DataTable ConvertToDataTable<T>(IList<T> data)
{
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
DataTable table = new DataTable();
foreach (PropertyDescriptor prop in properties)
table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
foreach (T item in data)
{
DataRow row = table.NewRow();
foreach (PropertyDescriptor prop in properties)
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
table.Rows.Add(row);
}
return table;
}
现在我想做一个update操作,有没有什么方法可以把数据从C#.Net更新到DataBase,因为插入数据是由SqlBulkCopy
完成的
发布于 2013-12-17 21:47:02
我之前所做的是执行从数据到临时表的大容量插入,然后使用命令或存储过程更新与临时表和目标表相关的数据。临时表是一个额外的步骤,但与逐行更新数据相比,如果行数很大,则使用批量插入和大规模更新可以获得性能提升。
示例:
public static void UpdateData<T>(List<T> list,string TableName)
{
DataTable dt = new DataTable("MyTable");
dt = ConvertToDataTable(list);
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["SchoolSoulDataEntitiesForReport"].ConnectionString))
{
using (SqlCommand command = new SqlCommand("", conn))
{
try
{
conn.Open();
//Creating temp table on database
command.CommandText = "CREATE TABLE #TmpTable(...)";
command.ExecuteNonQuery();
//Bulk insert into temp table
using (SqlBulkCopy bulkcopy = new SqlBulkCopy(conn))
{
bulkcopy.BulkCopyTimeout = 660;
bulkcopy.DestinationTableName = "#TmpTable";
bulkcopy.WriteToServer(dt);
bulkcopy.Close();
}
// Updating destination table, and dropping temp table
command.CommandTimeout = 300;
command.CommandText = "UPDATE T SET ... FROM " + TableName + " T INNER JOIN #TmpTable Temp ON ...; DROP TABLE #TmpTable;";
command.ExecuteNonQuery();
}
catch (Exception ex)
{
// Handle exception properly
}
finally
{
conn.Close();
}
}
}
}
请注意,使用单个连接执行整个操作,以便能够在每个步骤中使用临时表,因为临时表的作用域是每个连接。
发布于 2013-12-27 01:19:36
根据我的个人经验,处理这种情况的最好方法是使用具有Table-Valued Parameter
和User-Defined Table Type
的存储过程。只需使用数据表的列设置类型,并将所述- data表作为参数传入SQL命令。
在存储过程中,您可以直接在某个唯一键上联接(如果要更新的所有行都存在),或者-如果您可能遇到必须同时执行更新和插入的情况-在存储过程中使用SQL Merge
命令来处理更新和插入。
微软同时拥有用于合并的syntax reference和article with examples。
对于.NET片段,只需将参数类型设置为SqlDbType.Structured
,并将所述参数的值设置为包含您想要更新的记录的数据表。
这种方法提供了清晰度和易于维护的优点。虽然可能有一些方法可以提供性能改进(例如将其放到临时表中,然后迭代该表),但我认为让.NET和SQL处理表传输和记录本身更新的简单性超过了这些方法。K.I.S.
发布于 2016-09-13 21:06:28
尝试在Nuget上使用SqlBulkTools。
免责声明:我是这个库的作者。
var bulk = new BulkOperations();
var records = GetRecordsToUpdate();
using (TransactionScope trans = new TransactionScope())
{
using (SqlConnection conn = new SqlConnection(ConfigurationManager
.ConnectionStrings["SqlBulkToolsTest"].ConnectionString))
{
bulk.Setup<MyTable>()
.ForCollection(records)
.WithTable("MyTable")
.AddColumn(x => x.SomeColumn1)
.AddColumn(x => x.SomeColumn2)
.BulkUpdate()
.MatchTargetOn(x => x.Identifier)
.Commit(conn);
}
trans.Complete();
}
只会更新'SomeColumn1‘和'SomeColumn2’。有关更多示例,请访问here
https://stackoverflow.com/questions/20635796
复制相似问题