9

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

谢谢!

4

4 回答 4

2

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

我会简单地创建一个DataTable自己,除非我可以证明一个真正的内存问题可以证明实施是合理的。

于 2009-11-19T00:52:16.827 回答
1

正如迈克尔所说,您当然可以实现一个 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 ) ) );
于 2009-11-19T01:27:25.443 回答
0

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

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

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

希望能帮助到你。

于 2013-07-09T15:05:29.987 回答
0

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

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

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

于 2009-11-19T01:17:36.283 回答