使用OleDbParameter为Access创建表

时间:2017-10-20 15:41:11

标签: c# ms-access oledb

我目前正在通过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)

1 个答案:

答案 0 :(得分:2)

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

例如。对于VarWChar类型的列,您需要传递字符串&#34; TEXT&#34;后跟字段的大小,而对于一个整数类型的字段,你需要字符串&#34; INT&#34;

#include <tuple>
#include <type_traits>

template <template <typename> class Pred, typename>
struct PredValFirst : public std::false_type
 { };

template <template <typename> class Pred,
          template <typename...> class C,
          typename T0, typename ... Ts>
struct PredValFirst<Pred, C<T0, Ts...>> : public Pred<T0>
 { };


template <template <typename> class Pred, typename List,
          typename = std::tuple<>, typename = std::tuple<>,
          bool = PredValFirst<Pred, List>::value>
struct SplitTypeList;

template <template <typename> class Pred, template <typename...> class C,
          typename T0, typename ... Ts, typename ... Tt, typename Lf>
struct SplitTypeList<Pred, C<T0, Ts...>, std::tuple<Tt...>, Lf, true>
   : SplitTypeList<Pred, C<Ts...>, std::tuple<Tt..., T0>, Lf>
 { };

template <template <typename> class Pred, template <typename...> class C,
          typename T0, typename ... Ts, typename Lt, typename ... Tf>
struct SplitTypeList<Pred, C<T0, Ts...>, Lt, std::tuple<Tf...>, false>
   : SplitTypeList<Pred, C<Ts...>, Lt, std::tuple<Tf..., T0>>
 { };

template <template <typename> class Pred, template <typename...> class C,
          typename ... Tt, typename ... Tf>
struct SplitTypeList<Pred, C<>, std::tuple<Tt...>, std::tuple<Tf...>, false>
 {
   using types_true  = C<Tt...>;
   using types_false = C<Tf...>;
 };

template <typename...>
struct TypeList
 { };

struct A
 { };

int main ()
 {
   using typeList = TypeList<int, double, float, A, int>;

   using splited_typeList = SplitTypeList<std::is_floating_point, typeList>;

   using float_typeList = splited_typeList::types_true;
   using other_typeList = splited_typeList::types_false;

   static_assert( std::is_same<float_typeList,
                               TypeList<double, float>>{}, "!");
   static_assert( std::is_same<other_typeList,
                               TypeList<int, A, int>>{}, "!");
 }

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

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

   }
}

您可以在此SQL Data Types

找到一些允许的类型