使用 SQL Bulk Copy 与您的 LINQ-to-Entities 数据上下文 - 第一部分





5.00/5 (1投票)
本技巧展示了如何使用实体框架显著提高大量数据插入的速度。
引言
Linq-to-Entities 在很多方面都很出色,但在处理大量插入时表现不佳。 通过扩展数据上下文的局部类,并使用以下代码可以解决这个问题。 您只需像往常一样创建 LINQ 实体,然后调用 datacontext
上的 BulkInsertAll
方法即可。 另外,在执行批量插入之前,请勿将此 datacontext
用于其他任何操作。 由于某种原因,我们在此处用于创建 SQLConnection
的 datacontext
的连接字符串在第一次使用后会丢失密码,这显然会使连接变得有些困难。 这也发布在我的 博客上。 如果您使用的是 POCO 对象和 EF5,请参阅 此处
public partial class MyEntities
{
partial void OnContextCreated()
{
CommandTimeout = 5 * 60;
}
public void BulkInsertAll<t>(IEnumerable<t> entities)
{
entities = entities.ToArray();
var ec = (EntityConnection) Connection;
var conn = (SqlConnection) ec.StoreConnection;
conn.Open();
Type t = typeof(T);
var entityTypeAttribute = (EdmEntityTypeAttribute)t.GetCustomAttributes
(typeof(EdmEntityTypeAttribute), false).Single();
var bulkCopy = new SqlBulkCopy(conn) { DestinationTableName = entityTypeAttribute.Name };
var properties = t.GetProperties().Where(EventTypeFilter).ToArray();
var table = new DataTable();
foreach (var property in properties)
{
Type propertyType = property.PropertyType;
if (propertyType.IsGenericType &&
propertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
{
propertyType = Nullable.GetUnderlyingType(propertyType);
}
table.Columns.Add(new DataColumn(property.Name, propertyType));
bulkCopy.ColumnMappings.Add(new SqlBulkCopyColumnMapping(property.Name, property.Name));
}
foreach (var entity in entities)
{
var e = entity;
table.Rows.Add(properties.Select(property =>
GetPropertyValue(property.GetValue(e, null))).ToArray());
}
bulkCopy.WriteToServer(table);
conn.Close();
}
private bool EventTypeFilter(System.Reflection.PropertyInfo p)
{
var attribute = Attribute.GetCustomAttribute(p,
typeof(EdmScalarPropertyAttribute)) as EdmScalarPropertyAttribute;
if (attribute != null) return true;
return false;
}
private object GetPropertyValue(object o)
{
if (o == null)
return DBNull.Value;
return o;
}
}