65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2013年8月26日

CPOL
viewsIcon

17011

本技巧展示了如何使用实体框架显著提高大量数据插入的速度。

引言

Linq-to-Entities 在很多方面都很出色,但在处理大量插入时表现不佳。 通过扩展数据上下文的局部类,并使用以下代码可以解决这个问题。 您只需像往常一样创建 LINQ 实体,然后调用 datacontext 上的 BulkInsertAll 方法即可。 另外,在执行批量插入之前,请勿将此 datacontext 用于其他任何操作。 由于某种原因,我们在此处用于创建 SQLConnectiondatacontext 的连接字符串在第一次使用后会丢失密码,这显然会使连接变得有些困难。 这也发布在我的 博客上。 如果您使用的是 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;
    }
}
© . All rights reserved.