Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/267.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
ADO.NET+;大量插入+;Excel+;C#=”等;“糟糕的时刻”吗;?_C#_Excel_Ado.net_Memory Management_Memory Leaks - Fatal编程技术网

ADO.NET+;大量插入+;Excel+;C#=”等;“糟糕的时刻”吗;?

ADO.NET+;大量插入+;Excel+;C#=”等;“糟糕的时刻”吗;?,c#,excel,ado.net,memory-management,memory-leaks,C#,Excel,Ado.net,Memory Management,Memory Leaks,基本上,我需要在Excel文件中插入一组数据。创建OleDB连接似乎是最快的方法,但我发现它遇到了内存问题。当我执行INSERT查询时,进程使用的内存似乎在不断增长。我已经将它们缩小到只在输出到Excel文件时发生(内存保持稳定,没有输出到Excel)。我关闭并重新打开每个工作表之间的连接,但这似乎对内存使用没有影响(Dispose()也是如此)。数据编写成功,因为我可以用相对较小的数据集进行验证。如果有人有见解,我们将不胜感激 在构造函数中调用initializeADOConn() inita

基本上,我需要在Excel文件中插入一组数据。创建OleDB连接似乎是最快的方法,但我发现它遇到了内存问题。当我执行INSERT查询时,进程使用的内存似乎在不断增长。我已经将它们缩小到只在输出到Excel文件时发生(内存保持稳定,没有输出到Excel)。我关闭并重新打开每个工作表之间的连接,但这似乎对内存使用没有影响(Dispose()也是如此)。数据编写成功,因为我可以用相对较小的数据集进行验证。如果有人有见解,我们将不胜感激

在构造函数中调用initializeADOConn()

initadoconnisercomm()创建插入参数化插入查询

每当写入新记录时,都会调用writeRecord()。根据需要创建新工作表

public bool initializeADOConn()
        {
            /* Set up the connection string and connect.*/
            string connectionString = @"Provider=Microsoft.Jet.OLEDB.4.0;" +
                "Data Source=" + this.destination + ";Extended Properties=\"Excel 8.0;HDR=YES;\"";
            //DbProviderFactory factory =
                //DbProviderFactories.GetFactory("System.Data.OleDb");
            conn = new OleDbConnection(connectionString);
            conn.ConnectionString = connectionString;
            conn.Open();

            /* Intialize the insert command. */
            initADOConnInsertComm();
            return true;
        }
    public override bool writeRecord(FileListerFileInfo file)
            {
                /* If all available sheets are full, make a new one. */
                if (numWritten % EXCEL_MAX_ROWS == 0)
                {
                    conn.Close();
                    conn.Open();
                    createNextSheet();
                }
                /* Count this record as written. */
                numWritten++;
                /* Get all of the properties of the FileListerFileInfo record and add
                 * them to the parameters of the insert query. */
                PropertyInfo[] properties = typeof(FileListerFileInfo).GetProperties();
                for (int i = 0; i < insertComm.Parameters.Count; i++)
                    insertComm.Parameters[i].Value = properties[i].GetValue(file, null);
                /* Add the record. */
                insertComm.ExecuteNonQuery();

                return true;
            }
public bool initializeADOConn()
{
/*设置连接字符串并连接*/
字符串连接字符串=@“Provider=Microsoft.Jet.OLEDB.4.0;”+
“数据源=“+this.destination+”“扩展属性=\”Excel 8.0;HDR=YES;\”;
//DbProviderFactory工厂=
//dbProviderFactorys.GetFactory(“System.Data.OleDb”);
conn=新的OLEDB连接(connectionString);
conn.ConnectionString=连接字符串;
conn.Open();
/*初始化insert命令*/
initadoconnisercomm();
返回true;
}
公共覆盖布尔写入记录(FileListerFileInfo文件)
{
/*如果所有可用的工作表都已满,请重新制作一张*/
如果(numwrited%EXCEL\u MAX\u行==0)
{
康涅狄格州关闭();
conn.Open();
createNextSheet();
}
/*将此记录记为书面记录*/
numwrited++;
/*获取FileListerFileInfo记录的所有属性并添加
*将它们添加到insert查询的参数中*/
PropertyInfo[]properties=typeof(FileListerFileInfo).GetProperties();
对于(int i=0;i
编辑:


不,我根本不用Excel。我故意避免Interop.Excel,因为它的性能很差(至少从我对它的涉猎来看是这样)。

您能找到一种方法以大容量插入记录,而不是一次写入一条记录吗?我尽量不使用疯狂的数据集,但是有没有一种方法可以让你的所有插入首先发生在本地,然后让它们一下子上升?
此过程是否在后台打开Excel?这些过程之后会消失吗?

答案是是的,你所描述的公式确实相当于一个糟糕的时期

如果您手头有一个数据库(SQL Server或Access对此很有用),您可以将所有插入操作都插入到数据库表中,然后将该表一次全部导出到Excel电子表格中


一般来说,数据库擅长处理大量插入,而电子表格则不然。

以下是一些想法:

目标工作簿是否打开?有一个bug(),IIRC实际上位于Jet的OLEDB提供程序中(您正在使用),尽管在上面的文章中没有确认这一点

不管怎样,批量插入似乎是一条出路

您可以使用相同的Jet OLE DB提供程序来实现这一点:您所需要的只是一个单行表。你甚至可以在飞行中制造一个。要创建新的Excel工作簿,请使用连接字符串中不存在的xls文件执行
create TABLE
DDL,然后提供程序将为您创建工作簿,其中包含一个表示该表的工作表。您已连接到Excel工作簿,因此可以执行以下操作:

CREATE TABLE [EXCEL 8.0;DATABASE=C:\MyFabricatedWorkbook;HDR=YES].OneRowTable 
(
   x FLOAT
);
(IMO更好的做法是制作一个Jet数据库,即mdb文件)

使用
INSERT
创建虚拟行:

INSERT INTO [EXCEL 8.0;DATABASE=C:\MyFabricatedWorkbook;HDR=YES].OneRowTable (x) 
   VALUES (0);
然后,仍然使用与目标工作簿的连接,您可以使用类似于以下内容的方法创建一个派生表(DT1),其中包含要一次插入的
值:

INSERT INTO MyExcelTable (key_col, data_col)
SELECT DT1.key_col, DT1.data_col
FROM (
   SELECT 22 AS key_col, 'abc' AS data_col
   FROM [EXCEL 8.0;DATABASE=C:\MyFabricatedWorkbook;HDR=YES].OneRowTable
   UNION ALL
   SELECT 55 AS key_col, 'xyz' AS data_col
   FROM [EXCEL 8.0;DATABASE=C:\MyFabricatedWorkbook;HDR=YES].OneRowTable
   UNION ALL
   SELECT 99 AS key_col, 'efg' AS data_col
   FROM [EXCEL 8.0;DATABASE=C:\MyFabricatedWorkbook;HDR=YES].OneRowTable
) AS DT1;

编辑:不,我根本不用Excel。我故意避免Interop.Excel,因为它的性能很差(至少从我对它的涉猎中可以看出)。我理解你建议的方法,但为什么这样可以避免内存使用问题?因为你说过,“当我执行插入查询时,进程使用的内存似乎在不断增长”,因此一个插入查询会,如果不能真正治愈这种疾病,至少要尽量减少症状。在阅读了这份回复(并将我的老板与excel不适合这种情况的十几个原因联系起来)后,我说服了管理层不要依赖它。我已经有了一系列的输出选项,所以这并不重要。