EntityFramework进阶(四)- 实现批量新增

本系列原创博客代码已在EntityFramework6.0.0测试通过,转载请标明出处

我们可以结合Ado.Net的SqlBulkCopy实现SqlServer数据库的批量新增,其他类型的数据库的批量操作请参考对应驱动提供的方法来自定义实现

public virtual void BulkInsert(TEntity[] entities,int? batchSize=1000,Action<object, SqlRowsCopiedEventArgs> copyProcess=null, string conn = null)
        {
            TDbContext _context = GetContext(conn);
            var connection = (SqlConnection)_context.Database.Connection;
            connection.Open();
            Type type = typeof(TEntity);


            var objectContext = _context.GetObjectContext();

            var workspace = objectContext.MetadataWorkspace;

           // var mappings = EntityMappingExtensions.GetMappings(workspace, objectContext.DefaultContainerName, type.Name);


            var tableName = GetTableName<TEntity>(_context);
            var bulkCopy = new SqlBulkCopy(connection) { DestinationTableName = tableName };

            // Foreign key relations show up as virtual declared 
            // properties and we want to ignore these.
            var properties = type.GetProperties().Where(p => !p.GetGetMethod().IsVirtual).ToArray();
            var table = new DataTable();
            foreach (var property in properties)
            {
                Type propertyType = property.PropertyType;

                // Nullable properties need special treatment.
                if (propertyType.IsGenericType &&
                    propertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
                {
                    propertyType = Nullable.GetUnderlyingType(propertyType);
                }

                // Since we cannot trust the CLR type properties to be in the same order as
                // the table columns we use the SqlBulkCopy column mappings.
                table.Columns.Add(new DataColumn(property.Name, propertyType));
                var clrPropertyName = property.Name;
                var tableColumnName = property.Name;
                // var tableColumnName = mappings[property.Name];
                bulkCopy.ColumnMappings.Add(new SqlBulkCopyColumnMapping(clrPropertyName, tableColumnName));
            }
            
            // Add all our entities to our data table
            foreach (var entity in entities)
            {
                var e = entity;
                table.Rows.Add(properties.Select(property =>
                   EntityMappingExtensions.GetPropertyValue(property.GetValue(e, null))).ToArray());
            }
            if (batchSize.HasValue)
            {
                bulkCopy.BatchSize = batchSize.Value;
            }
            if (copyProcess != null)
            {
                bulkCopy.SqlRowsCopied += new SqlRowsCopiedEventHandler(copyProcess);
            }
            // send it to the server for bulk execution
            bulkCopy.WriteToServer(table);

            connection.Close();
        }


        private string GetTableName<T>(TDbContext context) where T : class
        {
            Type t = typeof(T);
            var attributes=t.GetCustomAttributes(typeof(TableAttribute), true);
            if (attributes.Length > 0)
            {
               return t.GetTypeInfo().GetCustomAttributes<TableAttribute>().FirstOrDefault().Name;
            }
            return t.Name;
            //var dbSet = context.Set<T>();
            //var sql = dbSet.ToString();
            //var regex = new Regex(@"FROM (?.*) AS");
            //var match = regex.Match(sql);
            //return match.Groups["table"].Value;
        }

 后续会再补充批量更新,批量删除的方法,区别新增操作,更新和删除是通用于MySql,Oracle,SqlServer(暂时提供这三种数据库),会动态创建sql来实现,用户不必再手写sql或者依赖其他库了

原文地址:https://www.cnblogs.com/RexSheng/p/10928441.html