C# 从DataTable中查找每行的大小

C# 从DataTable中查找每行的大小,c#,sql-server,sqlbulkcopy,C#,Sql Server,Sqlbulkcopy,我必须动态地找到批量复制的批大小,以避免可能的超时时间错误。 我打算通过查找行的大小来完成。如果每行的大小更大,则减小批处理的大小 这是我试过的 var values = new object[data.Length]; // add row values to values dataTable.Rows.Add(values); if (Marshal.SizeOf(values) > 2000) moreThan2000++; 根据超过2000的数据我将更新批量大小。但是,当

我必须动态地找到批量复制的批大小,以避免可能的超时时间错误。 我打算通过查找行的大小来完成。如果每行的大小更大,则减小批处理的大小

这是我试过的

var values = new object[data.Length];
// add row values to values 
dataTable.Rows.Add(values);
if (Marshal.SizeOf(values) > 2000)
   moreThan2000++;
根据
超过2000的数据
我将更新批量大小。但是,当我尝试使用
Marshal.SizeOf
SizeOf
获取值时,我得到了以下错误信息

类型“System.Object[]”不能作为非托管结构封送; 无法计算有意义的大小或偏移

  • 有没有办法从DataTable中找到行大小
  • 是否有基于系统规范和输入动态查找批量大小的现有方法

  • 没有任何精确的方法来计算托管对象的大小,但是您可以使用来获得粗略的估计

    大概是这样的:

    long start = GC.GetTotalMemory(true);
    
    var values = new object[data.Length];
    // add row values to values 
    dataTable.Rows.Add(values);
    
    long used = GC.GetTotalMemory(true) - start;
    

    used
    将是您使用过的内存。

    Marshal.SizeOf
    没有用处——对于许多简单类型,这或多或少取决于线路上TDS行的大小,但对于字符串(例如字符串)则没有好处,因为字符串的大小取决于您使用的是
    VARCHAR
    还是
    NVARCHAR
    。这里真正重要的是最终用于批量复制的本机类型。(另外,
    DataTable
    是一种为批量复制提供行的效率极低的方法,仅适用于小批量;查看
    IDataRecord
    )根据总大小调整批量复制超时听起来不是很有用的事情——为什么不将超时设置为0呢?@Jeroemoster,如果IDataRecord超过DataTable,您可以分享它的效率吗?
    IEnumerable
    除了一行所需的内存外,不消耗任何内存<代码>数据表消耗的内存与其中的数据量成线性关系。如果您正在从外部源生成或流式传输数据,
    IEnumerable
    beats
    DataTable
    可以直接使用内存(以及通过消除垃圾收集来节省时间)。这有多大的不同取决于您的场景,应该进行测试。对于小批量,数据表的开销无关紧要。对于非常大的数据集,只需缩短填充
    DataTable
    的时间是可以测量的,更不用说复制本身了。
    DataTable
    及其所有子对象使用的内存量与大容量副本中发送的数据的大小只有非常微弱的关系,因为数据布局完全不同(TDS大容量复制数据包是一个平面数组;
    DataTable
    使用红/黑树,加上受管字节与TDS中发送的内容没有一对一的关系)。通过大量实验,您可能会得到一个神奇的值,表明该批数据“太大”,但这是非常不可靠的。可能比(比如)更糟糕只需将所有字符串的长度相加。