c# - OracleBulkCopy 能否将数据从我的进程地址空间移动到表中?

标签 c# oracle etl bulkinsert odp.net

我希望加快一些大规模 ETL 操作的速度,这些操作从格式奇怪的平面文件和更奇怪的 XML 数据存储中读取和转换一堆内容,然后将许多记录插入到 Oracle dbms 中。我在 C#/dotnet 4 中使用 ODP.NET 11g。

OracleBulkCopy 类似乎是一个值得尝试的好东西。问题是,它想要从 IDataReader 实例或 IDataRecord 实例数组(即其他 dbms 查询的结果集)读取数据。

有没有一种简单的方法可以将我的数据行包装在内存中的 IDataReader 或 IDataRecord 类数组中,以便我可以将它们推送到 OracleBulkCopy 中?

我发现的示例显示了从一个数据库管理系统到另一个数据库管理系统的数据迁移。但是,我试图避免将这些项目逐一写入数据库管理系统,以便我可以批量加载它们。我宁愿使用 IDataReader 相当于内存流。谢谢。

最佳答案

我也遇到了类似的问题,我正在使用 Link2Sql 并发现性能问题。我找到了使用反射和扩展方法的解决方案,其中我从 ColumnAttribute 中读取列数据。

public static void Insert<T>(this OracleBulkCopy copy, IEnumerable<T> entities)
    where T : class
{
    var properties = typeof(T).GetProperties();
    var columnNames = new List<string>();
    var columnPropertyNames = new List<string>();
    foreach (var propertyInfo in properties)
    {
        var attribute = Attribute.GetCustomAttribute(propertyInfo, typeof(ColumnAttribute)) as ColumnAttribute;
        if (attribute != null)
        {
            columnNames.Add(attribute.Name);
            columnPropertyNames.Add(propertyInfo.Name);
        }
    }

    copy.ColumnMappings.Clear();
    foreach (var columnName in columnNames)
    {
        copy.ColumnMappings.Add(columnName, columnName);
    }

    var table = new DataTable(copy.DestinationTableName);

    foreach (var columnMapping in copy.ColumnMappings)
    {
        table.Columns.Add(((OracleBulkCopyColumnMapping)columnMapping).DestinationColumn);
    }

    foreach (var entity in entities)
    {
        var row = table.NewRow();
        for (var i = 0; i < columnNames.Count; i++)
        {
            var value = typeof (T).GetProperty(columnPropertyNames[i]).GetValue(entity, null);
            if (value is DateTime)
                value = new OracleDate((DateTime) value);
            row[columnNames[i]] = value;
        }

        table.Rows.Add(row);
    }

    copy.WriteToServer(table);
}

实体看起来像:

public class SomeEntity
{
  [Column(Name = "Id")]
  public string Id { get; set; }
  //more columns
}

使用它非常简单:

using (var connection = CreateDbConnection())
{
    connection.Open();
    using (var copy = new OracleBulkCopy(connection))
    {
        copy.DestinationTableName = tableName;
        copy.BulkCopyTimeout = DefaultTimeoutInSeconds;
        copy.BatchSize = BatchSize;
        copy.Insert(entities);
    }
}

关于c# - OracleBulkCopy 能否将数据从我的进程地址空间移动到表中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7762182/

相关文章:

python - 未达到 Airflow 传感器超时

sql-server - SSIS发送邮件文件附件失败

Oracle Apex : How to execute procedure and display the results on a page

python - pandas 中的 .read_csv() 无法正确读取转义字符

c# - 使用 .exe 合并 XML 配置文件

c# - 这个错误是什么意思 : stale element reference: element is not attached to the page document?

sql - 触发器编译没有错误,但它不添加数据

oracle - Oracle在哪里进行过滤?

c# - 在特定的秒开始播放歌曲

c# - .NET 互操作 IntPtr 与 ref