【问题标题】:Write A DataTable with variable columns into a database table将具有可变列的 DataTable 写入数据库表
【发布时间】:2015-03-18 19:53:37
【问题描述】:

如果我使用SqlConnection,这可能会容易得多。但现在我有一个OleDbConnection,我想将整个DataTable 复制到一个数据库表中。 DataTable 每次可以有不同的列。所以我只想插入匹配的列。

如果不一直遍历我的 DataTable 列并根据它构建 INSERT 查询,我如何才能实现这一点?

【问题讨论】:

  • 拥有一个不断变化的结构,如果没有某种迭代,您将无法做到这一点
  • @Franck 是的。但是SqlBulkCopy 怎么可能存在这样的事情但是如果我使用OleDb 我必须一砖一瓦地经历这些事情?
  • 为什么不改连接不使用OleDB?
  • @SeanLange 到数据库的连接字符串具有 provider 值,SqlConnection 不支持。
  • 好吧,如果您要连接到 sql server,您是否可以更改应用程序,以便您拥有一个不会强迫您使用过时技术的连接字符串。或者也许在配置文件中添加第二个连接字符串?

标签: c# sql-server datatable oledb


【解决方案1】:

Pedram,当然可以。继续使用GetOleDbSchemaTable() 获取详细信息。

这是你前进的方式,

DataSet output = new DataSet();
using (OleDbConnection conn = new OleDbConnection(strConn))
{
    conn.Open();

    DataTable schemaTable = conn.GetOleDbSchemaTable(
        OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });

    // e.g. Rows in SchemaTable are Sheets in Xlsx file.
    foreach (DataRow schemaRow in schemaTable.Rows)
    {
        //... 
        string sheet = schemaRow["TABLE_NAME"].ToString();
        var select = "SELECT * FROM [" + sheet + "]";
        OleDbCommand cmd = new OleDbCommand(select, conn);
        cmd.CommandType = CommandType.Text;
        DataTable outputTable = new DataTable(sheet);
        output.Tables.Add(outputTable);
        new OleDbDataAdapter(cmd).Fill(outputTable);
    }
}

稍后,当您获得 DataSet 时,您可以使用 myDataSet.Tables 将您的 DataTables 从中取出,但是它们采用 DataTableCollection 类型,仅支持 Foreach 而不是 IEnumerable() 然后您可以在不需要迭代的情况下对其进行 LINQ 查询。由于多种原因,.NET 开发人员尚未决定实现此功能,您可以通过 here 广泛阅读。

但是有一个非常简单的解决方法,那就是铸造它。因此,如果您不想遍历集合并挑选您想要的条目,请继续并在 Method Syntax 中使用以下语法:

var foo = dataSet.Tables.Cast<DataTable>().Where(
            t => t.TableName == "The Table I want");

或以 查询语法 LINQ 形式为,

var bar = from DataTable t in dataSet.Tables
            where t.TableName == "The table I want" 
            select t;

希望我理解你的正确。因为我很好奇,所以我花了很多时间自己弄清楚这一点。

更新

批量复制

如果您想将整个表复制到 OleDbConnection 以实现类似于 SqlBulkCopySqlConnection 中所做的事情,您将希望使用 IRowsetFastLoad。您没有提到您使用的是 Ado.Net 还是纯 OleDb。如果它是第一个选项并且您正在使用 C#,不幸的是 IRowsetFastLoad 未在此平台上实现,仅在 C++ 上实现。在这种情况下,您正在考虑迭代和磨牙。

另一方面,如果SqlBulkCopy 是一个选项,我很确定你已经完成了。如果没有,请快速查看以下文章。它清除了很多东西。

Using SqlBulkCopy to efficiently copy table from Access to SQL Server

我在 Google 上进行了快速搜索,发现了使用 adapter.Update() 等解决方案,但我以前没有使用过这种方法,并且未经测试无法对其发表评论。

DbDataAdapter.Update Method (DataTable)

可能值得一看。抱歉,虽然回答了一半。我必须通过您的 cmets 才能完全了解您想要完成的任务。

【讨论】:

  • 嘿梅赫拉德!您提供的代码 sn-p 看起来非常优雅。但是,我已经有了源DataTable 和目标表的名称。我想做的是将DataTable 中的所有行插入到目标表中。您是否认为您的代码中的某个地方提供了我忽略的答案?
  • 我认为像stackoverflow.com/questions/9075159/… 这样的解决方案会以某种方式完成这项工作。你不觉得吗?
  • 抱歉,我不确定。应该做一些测试。
  • 我会说建议的链接也是一个 SQL 解决方案,如果您采用这种方式,可以使用 SqlBulkCopy 代替。我也更新了我的答案。请看一下,让我们知道您的情况。
  • SqlBulkCopy 仅适用于 SqlConnection 而不是 OleDbConnection
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多