有没有办法使用SqlBulkCopy而不将数据转换为DataTable?

时间:2009-11-19 00:41:06

标签: c# sql-server sqlbulkcopy

有没有办法在不将数据转换为DataTable的情况下使用SqlBulkCopy?我在RAM中有一个对象列表(List),我真的不想使用更多的内存来创建DataTable。是否可以在List上实现IDataReader?

谢谢!

4 个答案:

答案 0 :(得分:2)

我当然会想象你可以。 BulkDataReader需要架构信息;这就是为什么你不能简单地提供List。如果您设计了一个实现IDataReader的类,那么您将在GetSchemaTable实现中提供此类。

我只想自己创建一个DataTable,除非我能证明一个真正的内存问题,证明这个实现是合理的。

答案 1 :(得分:1)

正如Michael所说,你当然可以实现一个IDataReader,这是最有效的方法,但还需要一些额外的工作。实现GetSchemaTable是一种很难实现,但如果你使用下面的代码作为起点,那就没那么糟了。

        var table = new DataTable( "SchemaTable" );
        table.Locale = CultureInfo.InvariantCulture;

        table.Columns.Add( new DataColumn( SchemaTableColumn.ColumnName, typeof( string ) ) );
        table.Columns.Add( new DataColumn( SchemaTableColumn.ColumnOrdinal, typeof( int ) ) );
        table.Columns.Add( new DataColumn( SchemaTableColumn.ColumnSize, typeof( int ) ) );
        table.Columns.Add( new DataColumn( SchemaTableColumn.NumericPrecision, typeof( short ) ) );
        table.Columns.Add( new DataColumn( SchemaTableColumn.NumericScale, typeof( short ) ) );
        table.Columns.Add( new DataColumn( SchemaTableColumn.DataType, typeof( Type ) ) );
        table.Columns.Add( new DataColumn( SchemaTableOptionalColumn.ProviderSpecificDataType, typeof( Type ) ) );
        table.Columns.Add( new DataColumn( SchemaTableColumn.NonVersionedProviderType, typeof( int ) ) );
        table.Columns.Add( new DataColumn( SchemaTableColumn.ProviderType, typeof( int ) ) );
        table.Columns.Add( new DataColumn( SchemaTableColumn.IsLong, typeof( bool ) ) );
        table.Columns.Add( new DataColumn( SchemaTableColumn.AllowDBNull, typeof( bool ) ) );
        table.Columns.Add( new DataColumn( SchemaTableOptionalColumn.IsReadOnly, typeof( bool ) ) );
        table.Columns.Add( new DataColumn( SchemaTableOptionalColumn.IsRowVersion, typeof( bool ) ) );
        table.Columns.Add( new DataColumn( SchemaTableColumn.IsUnique, typeof( bool ) ) );
        table.Columns.Add( new DataColumn( SchemaTableColumn.IsKey, typeof( bool ) ) );
        table.Columns.Add( new DataColumn( SchemaTableOptionalColumn.IsAutoIncrement, typeof( bool ) ) );
        table.Columns.Add( new DataColumn( SchemaTableOptionalColumn.IsHidden, typeof( bool ) ) );
        table.Columns.Add( new DataColumn( SchemaTableOptionalColumn.BaseCatalogName, typeof( string ) ) );
        table.Columns.Add( new DataColumn( SchemaTableColumn.BaseSchemaName, typeof( string ) ) );
        table.Columns.Add( new DataColumn( SchemaTableColumn.BaseTableName, typeof( string ) ) );
        table.Columns.Add( new DataColumn( SchemaTableColumn.BaseColumnName, typeof( string ) ) );
        table.Columns.Add( new DataColumn( SchemaTableOptionalColumn.BaseServerName, typeof( string ) ) );
        table.Columns.Add( new DataColumn( SchemaTableColumn.IsAliased, typeof( bool ) ) );
        table.Columns.Add( new DataColumn( SchemaTableColumn.IsExpression, typeof( bool ) ) );

答案 2 :(得分:0)

当您将每个对象移动到DataTable时,将其从List中删除,然后您可以使用SqlBulkCopy,只需要一点额外的内存。

然后,当你完成后,将其反转。

就个人而言,我只会创建一个DataTable,因为内存很便宜。

答案 3 :(得分:0)

查看此链接http://code.msdn.microsoft.com/LinqEntityDataReader,您实际上可以从对象列表或支持IQueryable的任何内容中进行投影,该投影将转换为可传递给SqlBulkCopy对象的DataReader。

var q = from o in orders
         select new 
         {
           ID=o.ID,
           ShipDate=o.ShipDate,
           ProductName=o.Product.Name,
           ...
         }
IDataReader dr = q.AsDataReader();

我认为这个库会派上用场,因为它可以为您节省一些工作。

希望它有所帮助。