我想从数据表批量插入到SQL Server。问题是我想从datatable批量插入特殊列到SQL Server。
我该怎么办?
SqlConnection con = new SqlConnection(connectionazmoonak);
SqlBulkCopy bulk = new SqlBulkCopy(con);
bulk.DestinationTableName = "targetTable";
DataSet ds = new DataSet();
ds.Tables.Add(targetTable);
foreach (DataColumn col in ds.Tables[0].Columns)
bulk.ColumnMappings.Add(col.ColumnName, col.ColumnName);
con.Open();
bulk.WriteToServer(ds.Tables[0]);
con.Close();
此代码有效,但会插入所有列。请帮帮我。
答案 0 :(得分:0)
是的,是的,您需要将所有内容批量插入表格(临时表),然后从那里将所需内容加载到最终的生产表中。看看下面的链接。
https://www.quora.com/What-is-staging-table
So, use a Staging Table for:
De-duping
Cleansing
Normalizing to multiple tables
De-Normalizing from multiple to a single table.
Extrapolating
etc.
这应该会给你一些如何让这个工作符合你自己的想法。
答案 1 :(得分:0)
我在过去两天一直在处理批量插入,这是一个通用批量插入类(此类允许您排除某些列):
/// <summary>
/// This class is intended to perform a bulk insert of a list of elements into a table in a Database.
/// This class also allows you to use the same domain classes that you were already using because you
/// can include not mapped properties into the field excludedPropertyNames.
/// </summary>
/// <typeparam name="T">The class that is going to be mapped.</typeparam>
public class BulkInsert<T> where T : class
{
#region Fields
private readonly LoggingService _logger = new LoggingService(typeof(BulkInsert<T>));
private string _connectionString;
private string _tableName;
private IEnumerable<string> _excludedPropertyNames;
private int _batchSize;
private IEnumerable<T> _data;
private DataTable _dataTable;
#endregion
#region Constructor
/// <summary>
/// Initializes a new instance of the <see cref="BulkInsert{T}"/> class.
/// </summary>
/// <param name="connectionString">The connection string.</param>
/// <param name="tableName">Name of the table.</param>
/// <param name="data">The data.</param>
/// <param name="excludedPropertyNames">The excluded property names.</param>
/// <param name="batchSize">Size of the batch.</param>
public BulkInsert(
string connectionString,
string tableName,
IEnumerable<T> data,
IEnumerable<string> excludedPropertyNames,
int batchSize = 1000)
{
if (string.IsNullOrEmpty(connectionString)) throw new ArgumentNullException(nameof(connectionString));
if (string.IsNullOrEmpty(tableName)) throw new ArgumentNullException(nameof(tableName));
if (data == null) throw new ArgumentNullException(nameof(data));
if (batchSize <= 0) throw new ArgumentOutOfRangeException(nameof(batchSize));
_connectionString = connectionString;
_tableName = tableName;
_batchSize = batchSize;
_data = data;
_excludedPropertyNames = excludedPropertyNames == null ? new List<string>() : excludedPropertyNames;
_dataTable = CreateCustomDataTable();
}
#endregion
#region Public Methods
/// <summary>
/// Inserts the data with a bulk copy inside a transaction.
/// </summary>
public void Insert()
{
using (var connection = new SqlConnection(_connectionString))
{
connection.Open();
SqlTransaction transaction = connection.BeginTransaction();
using (var bulkCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.Default | SqlBulkCopyOptions.KeepIdentity, transaction))
{
bulkCopy.BatchSize = _batchSize;
bulkCopy.DestinationTableName = _tableName;
// Let's fix tons of mapping issues by
// Setting the column mapping in SqlBulkCopy instance:
foreach (DataColumn dataColumn in _dataTable.Columns)
{
bulkCopy.ColumnMappings.Add(dataColumn.ColumnName, dataColumn.ColumnName);
}
try
{
bulkCopy.WriteToServer(_dataTable);
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
transaction.Rollback();
connection.Close();
}
}
transaction.Commit();
}
}
#endregion
#region Private Helper Methods
/// <summary>
/// Creates the custom data table.
/// </summary>
private DataTable CreateCustomDataTable()
{
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
var table = new DataTable();
foreach (PropertyDescriptor prop in properties)
{
// Just include the not excluded columns
if (_excludedPropertyNames.All(epn => epn != prop.Name))
{
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)
{
// Just include the values in not excluded properties
if (_excludedPropertyNames.All(epn => epn != prop.Name))
{
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
}
}
table.Rows.Add(row);
}
return table;
}
#endregion
}
而且,它必须像:
一样使用var myEntityBulk = new BulkInsert<MyEntity>(
_mYConnectionString,
"MyEntities",
myEntities,
new[] { "ObjectState","NavigationPropertyOne", "NavigationPropertyTwo" }
);
myEntityBulk.Insert();
我希望它有所帮助,我确信它会...
注意:对我来说,下一步是自定义映射,例如从DbGeography到SqlGeography,因为我的一些实体在正常执行期间由我的域clases中的EF存储库和I DbGeography属性管理,但SqlBulkCopy仅管理SqlGeography属性。我会考虑它,也许我会更新我的答案。