You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

异步流式处理大XML写入Oracle CLOB的类库及代码优化咨询

问题

询问是否存在可异步流式处理大型XML并存储至Oracle CLOB列的类库。目前正在开发通用的XML流式读写至Oracle XML CLOB的功能,多方检索未找到适配类库,现有代码需优化——将每次读取插入新记录改为更新CLOB列,以下是两种实现代码及并行化方案:

现有实现代码1

static async Task Main()
{
    const string connectionString = "<your connection string>";
    const string tableName = "<your table name>";
    const int chunkSize = 100000;

    using var connection = new OracleConnection(connectionString);
    await connection.OpenAsync();
    using var transaction = connection.BeginTransaction();
    using var command = connection.CreateCommand();
    command.Transaction = transaction;
    command.CommandText = $"INSERT INTO {tableName} (xml_clob) VALUES (:clob)";
    var parameter = new OracleParameter("clob", OracleDbType.Clob);

    const string filePath = "large-file.xml";
    using var reader = XmlReader.Create(filePath);
    var semaphore = new SemaphoreSlim(50);

    var tasks = new List<Task<int>>();
    var settings = new XmlWriterSettings
    {
        Indent = true,
        IndentChars = "    "
    };

    while (await reader.ReadAsync())
    {
        switch (reader.NodeType)
        {
            case XmlNodeType.Element:
                using var ms = new MemoryStream();
                using var writer = XmlWriter.Create(ms, settings);
                writer.WriteStartElement(reader.Name);
                if (reader.HasAttributes)
                {
                    while (reader.MoveToNextAttribute())
                    {
                        writer.WriteAttributeString(reader.Name, reader.Value);
                    }

                    reader.MoveToElement();
                }
                writer.Flush();
                ms.Seek(0, SeekOrigin.Begin);
                parameter.Value = new OracleClob(connection, true);
                using var clobWriter = new StreamWriter(parameter.Value, Encoding.Unicode);
                await ms.CopyToAsync(clobWriter.BaseStream);
                await clobWriter.FlushAsync();
                var task = command.ExecuteNonQueryAsync();
                tasks.Add(task);
                break;

            case XmlNodeType.EndElement:
                break;

            case XmlNodeType.Text:
                using var ms2 = new MemoryStream();
                using var writer2 = XmlWriter.Create(ms2);
                while (!reader.EOF)
                {
                    char[] buffer = new char[chunkSize];
                    int charsRead = await reader.ReadValueChunkAsync(buffer, 0, buffer.Length);

                    if (charsRead == 0)
                    {
                        break;
                    }

                    await writer2.WriteCharsAsync(buffer, 0, charsRead);
                }

                writer2.Flush();
                ms2.Seek(0, SeekOrigin.Begin);
                parameter.Value = new OracleClob(connection, true);
                using var clobWriter2 = new StreamWriter(parameter.Value, Encoding.Unicode);
                await ms2.CopyToAsync(clobWriter2.BaseStream);
                await clobWriter2.FlushAsync();
                var task2 = command.ExecuteNonQueryAsync();
                tasks.Add(task2);
                break;
        }
    }

    await Task.WhenAll(tasks);
    await transaction.CommitAsync();
    Console.WriteLine($"Finished processing XML file '{filePath}'");
}

并行化提升写入速度的方案

using Oracle.ManagedDataAccess.Client;
using System;
using System.IO;
using System.Threading.Tasks;

public async Task SaveFileToOracleClobParallel(string filePath, string connectionString)
{
    const int bufferSize = 81920; // 80KB buffer size
    const int maxDegreeOfParallelism = 4; // maximum number of tasks to run in parallel

    try
    {
        using (var connection = new OracleConnection(connectionString))
        {
            await connection.OpenAsync();

            using (var transaction = connection.BeginTransaction())
            using (var command = connection.CreateCommand())
            {
                command.Transaction = transaction;
                command.CommandText = "INSERT INTO MyTable (MyClobColumn) VALUES (:clob)";

                using (var clob = new OracleClob(connection))
                {
                    await clob.OpenAsync(OracleDbType.Clob, System.Data.ConnectionState.Open);

                    var tasks = new List<Task>();

                    using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, FileOptions.SequentialScan))
                    {
                        for (int i = 0; i < maxDegreeOfParallelism; i++)
                        {
                            tasks.Add(ReadAndWriteChunkAsync(stream, clob, bufferSize));
                        }

                        await Task.WhenAll(tasks);
                    }

                    await clob.CloseAsync();
                    command.Parameters.Add(new OracleParameter("clob", OracleDbType.Clob) { Value = clob });

                    await command.ExecuteNonQueryAsync();
                    await transaction.CommitAsync();
                }
            }
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Error: {ex.Message}");
        // Handle the exception as appropriate
    }
}

private async Task ReadAndWriteChunkAsync(Stream stream, OracleClob clob, int bufferSize)
{
    var buffer = new byte[bufferSize];
    int bytesRead;

    while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
    {
        await clob.WriteAsync(buffer, 0, bytesRead);
    }
}

内容的提问来源于stack exchange,提问作者Keep Learning

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 06:35:14