1

我无法确定执行此操作的最佳方法。我们正在维护一个复杂的数据库,普通的业务分析师会遇到很多麻烦。另一位开发人员创建了几个存储过程作为报告,我们一直在为用户按需导出到 Excel 电子表格中。

客户要求将这些结果导出到访问数据库中。

如果这是 2 或 3 列,我只需创建一个“模板”accdb 文件并将存储过程的结果推送到其中。然而,这个查询现在带回了 100 多列,并且知道客户,它将在未来扩展。所以我试图从结果集中动态创建表......不管它是什么。

我/认为/这样做的正确方法是使用 aSqlDataReader但我坚持如何获得正确的“SQL”-ish 字段类型。我当前的代码如下所示:

static void CreateAccessTableFromReader(string tableName, SqlDataReader reader) {
  List<string> columns = new List<string>();
  string createTable = @"CREATE TABLE {0} ({1})";

  int fieldCount = reader.FieldCount;
  for (int i = 0; i < fieldCount; i++) {
    columns.Add(String.Format("[{0}] {1}({2})",
      //column name (this seems to be right)
      reader.GetName(i), 
      //column type __(this is wrong.. I want 'VARCHAR, INT, etc')__
      reader.GetProviderSpecificFieldType(i),
      //column size (e.g. the numeric part of VARCHAR(15))
      reader.???
    ));
    //right now I'm getting results from the above line like:
    //[ColumnName] System.Data.SqlTypes.SqlString
    //and I'm looking for something like:
    //[ColumnName] VARCHAR(15)
  }
  using (var cmd = conn_Access.CreateCommand()) {
    cmd.CommandType = CommandType.Text;
    cmd.CommandText = String.Format(createTable, tableName, String.Join(", ", columns));
    cmd.ExecuteNonQuery();
  }
}

值得注意:

编辑

这是我的“最终解决方案”。建议使用链接服务器的评论肯定会是一种更简单的方法,但是有一件事情阻止我做一开始我没有想到的事情,数据需要存在于 Access DB 中,因为用户可能会使用数据远离他们可以通过网络访问底层数据库的地方。因此,我一直在尝试这种方法,这就是我想出的:

请注意,我仍然愿意接受“更好的方法”的建议,但这解决了我目前的问题

static void CreateTableFromReader(string tableName, SqlDataReader reader) {
  List<string> columns = new List<string>();
  string createTable = @"CREATE TABLE {0} ({1})";

  var dt = reader.GetSchemaTable();
  foreach (DataRow dr in dt.Rows) {
    switch (dr["DataTypeName"].ToString().ToLower()) {
      case "varchar":
        columns.Add(String.Format("[{0}] {1}({2})",
          dr["ColumnName"],
          dr["DataTypeName"],
          dr["ColumnSize"]
        ));
        break;
      case "money": //i know this is redundant but being explicit helps clarity sometimes
      case "date":
      case "integer":
      default:
        columns.Add(String.Format("[{0}] {1}",
          dr["ColumnName"],
          dr["DataTypeName"]
        ));
        break;
    }
  }
  using (var cmd = conn_Access.CreateCommand()) {
    cmd.CommandType = CommandType.Text;
    cmd.CommandText = String.Format(createTable, tableName, String.Join(", ", columns));
    cmd.ExecuteNonQuery();
  }
}
4

1 回答 1

1

这是我的“最终解决方案”。建议使用链接服务器的评论肯定会是一种更简单的方法,但是有一件事情阻止我做一开始我没有想到的事情,数据需要存在于 Access DB 中,因为用户可能会使用数据远离他们可以通过网络访问底层数据库的地方。因此,我一直在尝试这种方法,这就是我想出的:

请注意,我仍然愿意接受“更好的方法”的建议,但这解决了我目前的问题

static void CreateTableFromReader(string tableName, SqlDataReader reader) {
  List<string> columns = new List<string>();
  string createTable = @"CREATE TABLE {0} ({1})";

  var dt = reader.GetSchemaTable();
  foreach (DataRow dr in dt.Rows) {
    switch (dr["DataTypeName"].ToString().ToLower()) {
      case "varchar":
        columns.Add(String.Format("[{0}] {1}({2})",
          dr["ColumnName"],
          dr["DataTypeName"],
          dr["ColumnSize"]
        ));
        break;
      case "money": //i know this is redundant but being explicit helps clarity sometimes
      case "date":
      case "integer":
      default:
        columns.Add(String.Format("[{0}] {1}",
          dr["ColumnName"],
          dr["DataTypeName"]
        ));
        break;
    }
  }
  using (var cmd = conn_Access.CreateCommand()) {
    cmd.CommandType = CommandType.Text;
    cmd.CommandText = String.Format(createTable, tableName, String.Join(", ", columns));
    cmd.ExecuteNonQuery();
  }
}
于 2013-02-06T16:46:58.307 回答