2017-10-20 286 views
0

我目前正在将表从SQL Server重建为通过C#访问。创建表使用OleDbParameter进行访问

为此我得到了SQL Server中使用的数据类型并将它们映射到OleDbType对象。

不幸的是,每次我试图执行我的Access语句时,都会抛出一个异常,在我的“创建表”语句中出现语法错误。我猜这是因为我只是将映射的数据类型添加为文本而不是OleDbParameters。

有没有办法创建OleDbParameter - 包含“Create Table”的列名和数据类型的对象 - 语句?

String accessConnectionString = "Provider=Microsoft.JET.OLEDB.4.0;Data 
Source=" + filepath; 

using (OleDbConnection accessConnection = new OleDbConnection(accessConnectionString)) 
{ 
    ADOX.Catalog cat = new ADOX.Catalog(); 
    cat.Create(accessConnectionString); 
    OleDbCommand oleCommand = new OleDbCommand(); 
    oleCommand.Connection = accessConnection; 
    oleCommand.CommandType = CommandType.Text; 
    accessConnection.Open(); 

    String columnsCommandText = "("; 

    for (int i = 0; i < reader.GetSchemaTable().Rows.Count; i++) // reader contains data from SQL Server 
    { 
     var column = reader.GetName(i); // name of attribute 
     SqlDbType type = (SqlDbType)(int)reader.GetSchemaTable().Rows[i]["ProviderType"]; // data type 
     var accessType = SQLAccessMapper.MapDataTypes(type); 
     columnsCommandText += " " + column + " " + accessType + ","; 
    } 

    columnsCommandText = columnsCommandText.Remove(columnsCommandText.Length - 1); 
    columnsCommandText += ")"; 

    oleCommand.CommandText = "CREATE TABLE " + tablename + columnsCommandText; 

    oleCommand.ExecuteNonQuery(); // Exception 

映射:

static class SQLAccessMapper 
{ 
    public static OleDbType MapDataTypes(SqlDbType sqlDataType) 
    { 
     switch (sqlDataType) 
     { 
      case SqlDbType.Int: 
       return OleDbType.Integer; 
      case SqlDbType.SmallInt: 
       return OleDbType.SmallInt; 
      case SqlDbType.TinyInt: 
       return OleDbType.TinyInt; 
      case SqlDbType.Decimal: 
       return OleDbType.Decimal; 
      case SqlDbType.Float:   
      case SqlDbType.Real: 
       return OleDbType.Single; 

      case SqlDbType.BigInt: 
       return OleDbType.BigInt; 
      case SqlDbType.Char: 
       return OleDbType.Char; 
      case SqlDbType.NChar: 
       return OleDbType.WChar; 
      case SqlDbType.NText:     
      case SqlDbType.NVarChar: 
      case SqlDbType.Text: 
       return OleDbType.VarWChar; 

      case SqlDbType.VarChar: 
       return OleDbType.VarChar; 
      case SqlDbType.Time: 
       return OleDbType.DBTime; 

      case SqlDbType.Date: 
       return OleDbType.DBDate; 

      case SqlDbType.DateTime: 
      case SqlDbType.DateTime2:     
      case SqlDbType.DateTimeOffset:     
      case SqlDbType.SmallDateTime: 
      case SqlDbType.Timestamp: 
       return OleDbType.DBTimeStamp; 

      case SqlDbType.Binary: 
       return OleDbType.Binary; 
      case SqlDbType.VarBinary: 
       return OleDbType.VarBinary; 

      case SqlDbType.Money: 
      case SqlDbType.SmallMoney: 
       return OleDbType.Currency; 

      case SqlDbType.Bit: 
       return OleDbType.Boolean; 
      default: return OleDbType.Error; 
     } 

    } 

} 

Create Table声明:

CREATE TABLE GrTable(
GrtId Integer, 
CaseId Integer, 
GrDrg VarChar, 
GrDrgText VarWChar, 
Mdc VarChar, 
MdcText VarWChar, 
GrPartition VarChar, 
Baserate Decimal, 
LosUsed Integer, 
Htp Integer, 
PricePerDay Decimal, 
Ltp Integer, 
LtpPricePerDay Decimal, 
AverLos Decimal, 
AverlosPricePerDay Decimal, 
Eff Decimal, 
Std Decimal, 
Adj Decimal, 
Gst VarChar, 
Pccl Integer, 
PriceEff Decimal, 
PriceStd Decimal, 
PriceAdj Decimal, 
DaysExcHtp Integer, 
DaysBelowLtp Integer, 
DaysBelowAverLos Integer, 
TotalPrice Decimal, 
BaseratePeriod VarChar) 
+2

AFAIK它是不可能的完成使用参数。你做这件事的方式是对的。只需解决'oleCommand.CommandText'中的值。我确定问题在那里。发布指定给CommandText的完整值,您可以使用调试器获取该值。 – andrews

+2

其中之一,'VARCHAR'列需要有一个明确的长度**定义 - 否则,你会最终列最大长度为1 .....这通常不是你想要的....使用'VARCHAR(n)'和**定义长度'n' **! –

回答

2

你的主要问题是在MapDataTypes。您应该返回MS-Access引擎所期望的字符串,而不像现在这样依赖于将常规枚举SqlDbType自动转换为字符串。

例如。对于VarWChar你需要传递字符串“TEXT”类型的列后跟字段的大小,而对于整数类型的字段,你需要的字符串“INT”

public static string MapDataTypes(SqlDbType sqlDataType) 
{ 
    switch (sqlDataType) 
    { 
     case SqlDbType.Int: 
      return "INT"; 
     case SqlDbType.VarChar: 
      return "TEXT(80)"; 

     ... AND SO ON FOR EVERY POSSIBLE TYPE 

    } 
} 

这当然,介绍了大小问题的文本字段,但可以从相同的GetSchemaTable检索用于查找名为ColumnSize列的类型,并通过这种规模的MapDataTypes方法 -

public static string MapDataTypes(SqlDbType sqlDataType, int size) 
{ 
    switch (sqlDataType) 
    { 
     case SqlDbType.Int: 
      return "INT"; 
     case SqlDbType.VarChar: 
      return "TEXT(" + size +)"; 
     ..... 


    } 
} 

你可以找到一些允许在这种类型SQL Data Types