【问题标题】:Create Table for Access using OleDbParameter使用 OleDbParameter 创建访问表
【发布时间】:2017-10-20 15:41:11
【问题描述】:

我目前正在通过 C# 将表从 SQL Server 重建到 Access。

为此,我正在获取 SQL Server 中使用的数据类型并将它们映射到 OleDbType 对象。

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

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

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)

【问题讨论】:

  • AFAIK 无法使用参数来完成。你这样做的方式是对的。只需对oleCommand.CommandText 中的值进行故障排除即可。我确定问题就在那里。发布分配给 CommandText 的完整值,您可以使用调试器获取该值。
  • 一方面,VARCHAR 列需要定义明确的长度 - 否则,您最终会得到最大长度为 1 .....通常不是您想要的......使用VARCHAR(n)定义长度n

标签: c# ms-access oledb


【解决方案1】:

您的主要问题在于 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

   }
}

这当然会引入 TEXT 字段的大小问题,但您可以从用于在名为 ColumnSize 的列中查找类型并将此大小传递给 MapDataTypes 方法的同一个 GetSchemaTable 中检索它-

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


   }
}

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

【讨论】:

    猜你喜欢
    • 2013-05-13
    • 1970-01-01
    • 1970-01-01
    • 2019-12-17
    • 2017-08-04
    • 1970-01-01
    • 1970-01-01
    • 2021-04-12
    相关资源
    最近更新 更多