0

问题:普遍的 odbc 驱动程序((称为:“普遍的 ODBC 引擎接口”)在 ODBC(odbcad32.exe) 中可见。但是,相同的 odbc 驱动程序在 SQL Server 2008 导入向导中不可见,尽管我可以看到相同的 odbc 驱动程序在 SQL Server 2000 导入向导中。

我正在使用带有 SQL server 2008、SQL server 2000 和普遍 SQL v11 的 32 位 win 7 操作系统。任何解决方案都会非常有帮助......非常感谢!

4

2 回答 2

1

我永远无法弄清楚如何使“导入/导出”向导在 Sql Server Management Studio 中工作。正如我在另一个响应中看到的那样,我什至尝试修改“ProviderResources.xml”文件。

我试图迁移使用专有的“Timberline Data”ODBC 驱动程序的 Sage Timberline Office 数据。当您在 .NET 中调用“GetSchema”函数时,该驱动程序缺少“ORDINAL_POSITION”列。因此 Sql Server Management Studio 中的“导入/导出”失败。

我最终不得不编写自己的应用程序来将数据复制到 SQL 服务器。唯一的缺点是它不知道主键、索引或其他约束。尽管如此,我还是在 MSSQL 中获得了数据,所以我很高兴。

我相信这段代码对其他人有用,所以你去吧。

程序.cs

using System;
using System.Data.Odbc;
using System.Data.SqlClient;
using System.Data;
using System.Collections.Generic;
using System.Diagnostics;

namespace TimberlineOdbcSync
{
    class Program
    {
        static string currentTableName;

        const string sourceOdbcDriver = "{Timberline Data}"; 
        const string sourceOdbcDsn = "timberline data source";
        const string sourceOdbcUid = "user1";
        const string sourceOdbcPwd = "user1a";

        const string destSqlServer = "SERVER5";
        const string destSqlDatabase = "TSData";
        const string destSqlUsername = "";
        const string destSqlPassword = "";
        const string destSqlOwner = "dbo";

        public static void Main(string[] args)
        {
            DateTime allStartDate = DateTime.Now;
            DateTime allEndDate;

            DateTime tableStartDate = DateTime.Now;
            DateTime tableEndDate;

            TimeSpan diff;

            string errMsg;

            int pCount; //pervasive record count
            int sCount; //sql server record count

            string sourceOdbcConnString =  
                "Dsn=" + sourceOdbcDsn + ";" +
                "Driver="+ sourceOdbcDriver +";" +
                    (!string.IsNullOrEmpty(sourceOdbcUid) ? "uid="+ sourceOdbcUid +";" : "") + 
                    (!string.IsNullOrEmpty(sourceOdbcUid) ? "pwd="+ sourceOdbcPwd +";" : "");

            string destSqlConnString = 
                "Server=" + destSqlServer + ";" + 
                "Database=" + destSqlDatabase+ ";" +
                (!string.IsNullOrEmpty(destSqlUsername) && !string.IsNullOrEmpty(destSqlPassword) ? 
                 "User Id=" + destSqlUsername + ";" + 
                 "Password=" + destSqlPassword + ";" 
                 :
                 "Trusted_Connection=true;");

            try{
                using(OdbcConnection pConn = new OdbcConnection(sourceOdbcConnString)){

                    pConn.Open();

                    List<string> tables = new List<string>();

                    //get a list of all tables
                    using(DataTable tableschema = pConn.GetSchema("TABLES"))
                        foreach(DataRow row in tableschema.Rows)
                            tables.Add(row["TABLE_NAME"].ToString());

                    foreach(string tableName in tables){

                        //set the current table name
                        currentTableName = tableName;

                        try{

                            //get the schema info for the table (from pervasive)
                            DataTable dtSchema = pConn.GetSchema("Columns", new string[]{null, null, tableName});

                            //if we could not get the schema
                            if(dtSchema == null || dtSchema.Rows.Count <= 0){
                                pConn.Close();
                                errMsg = "Error: Could not get column information for table " + tableName;
                                Trace.WriteLine(errMsg);
                                WriteErrorEvent(errMsg);
                                return;
                            }

                            //emit the table name
                            Trace.Write("[" + tableName + "]");

                            //get the number of records in this table
                            pCount = TableCount(tableName, pConn);

                            //emit the number of records in this table
                            Trace.Write(" = P:" + pCount);

                            //create a data reader to read the pervasive data
                            string sql = "select * from \""+ tableName + "\""; 
                            OdbcCommand cmd = new OdbcCommand(sql, pConn);
                            OdbcDataReader dr = cmd.ExecuteReader();

                            //create a connection to SQL Server
                            using (SqlConnection sConn = new SqlConnection(destSqlConnString)){

                                //open the connection
                                sConn.Open();

                                //if the table already exists
                                if(TableExists(tableName, sConn)){

                                    //get the record count for this table
                                    sCount = TableCount(tableName, sConn);

                                } else {

                                    //set the record count to zero
                                    sCount = 0;
                                }

                                //output the record count
                                Trace.Write(", S: " + sCount);

                                //if the record counts match
                                if( pCount == sCount ){

                                    //output an indicator that we are skipping this table
                                    Trace.WriteLine(" -- Skipping");

                                    //skip this table and go to the next
                                    continue;   

                                }

                                //output a blank line
                                Trace.WriteLine("");

                                //create the table in SQL Server using the schema info from Pervasive
                                CreateTableInDatabase(dtSchema, destSqlOwner, tableName, sConn);

                                // Copies all rows to the database from the data reader.
                                using (SqlBulkCopy bc = new SqlBulkCopy(sConn))
                                {
                                    // Destination table with owner - 
                                    // this example does not check the owner names! It uses dbo exclusively.
                                    bc.DestinationTableName = "[" + destSqlOwner + "].[" + tableName + "]";
                                    bc.BulkCopyTimeout = 30;
                                    bc.BatchSize = 3000;
                                    bc.BulkCopyTimeout = 12000;

                                    // User notification with the SqlRowsCopied event
                                    bc.NotifyAfter = 1000;
                                    bc.SqlRowsCopied += new SqlRowsCopiedEventHandler(OnSqlRowsCopied);

                                    //output the date and time so we know when we started
                                    tableStartDate = DateTime.Now;
                                    Trace.WriteLine("Copying " + pCount + " records to " + destSqlServer + " - " + tableStartDate.ToString("g"));

                                    // Starts the bulk copy.
                                    bc.WriteToServer(dr);

                                    tableEndDate = DateTime.Now;
                                    diff = tableEndDate - tableStartDate;

                                    Trace.WriteLine(String.Format(
                                        "Completed {4} at {0}\r\nDuration: {1}:{2}:{3}",
                                          tableEndDate.ToString("g"),
                                          diff.Hours.ToString(), diff.Minutes.ToString(), diff.Seconds.ToString(),
                                          tableName));

                                    // Closes the SqlBulkCopy instance
                                    bc.Close();
                                }

                                dr.Close();

                            }
                        }catch(Exception ex){
                            errMsg = "Error: " + ex.Message + Environment.NewLine + 
                                              "Stack: " + ex.StackTrace + Environment.NewLine;
                            Trace.WriteLine(errMsg);
                            WriteErrorEvent(errMsg);
                            if( !ReadBool("Do you want to continue? [y/n]") ){
                                break;
                            }
                        }//end try
                    }//end for
                }//end using

                allEndDate = DateTime.Now;
                diff = allEndDate - allStartDate;

                Trace.WriteLine(
                    "Bulk copy operation complete" + Environment.NewLine +
                    "Started: " + allStartDate.ToString("g") +  Environment.NewLine + 
                    "Current: " + allEndDate.ToString("g") + Environment.NewLine +
                    String.Format("Duration: {0}:{1}:{2}", 
                        diff.Hours.ToString(), 
                        diff.Minutes.ToString(), 
                        diff.Seconds.ToString()));

            }catch(Exception ex){

                errMsg = 
                    "Error: " + ex.Message + Environment.NewLine +
                    "Stack: " + ex.StackTrace;

                Trace.WriteLine(errMsg);
                WriteErrorEvent(errMsg);

            }//end try

            Console.Write("Press any key to continue . . . ");
            Console.ReadKey(true);
        }

        static bool TableExists(string tableName, SqlConnection sqlConn){
            int retVal = 0;
            try{
                using(SqlCommand command = sqlConn.CreateCommand()){
                    command.CommandText = "IF OBJECT_ID('dbo." + tableName + "', 'U') IS NOT NULL SELECT 1 as res ELSE SELECT 0 as res";
                    retVal = Convert.ToInt32(command.ExecuteScalar());
                }
            }catch(Exception ex){
                string errMsg = 
                    "Error: Could not determine if table " + tableName + " exists."+ Environment.NewLine +
                    "Reason: " + ex.Message + Environment.NewLine + 
                    "Stack: " + ex.StackTrace;
                Trace.WriteLine(errMsg);
                WriteErrorEvent(errMsg);
                retVal = 0;
            }//end try
            return (retVal==1);
        }

        static int TableCount(string tableName, IDbConnection anyConn){
            int retVal = 0;
            try{
                using(IDbCommand command = anyConn.CreateCommand()){
                    command.CommandText = "SELECT count(*) FROM \"" + tableName + "\"";
                    retVal = Convert.ToInt32(command.ExecuteScalar());
                }
            }catch(Exception ex){
                string errMsg = 
                    "Error: Could not get table count for " + tableName + "." + Environment.NewLine +
                    "Reason: " + ex.Message + Environment.NewLine + 
                    "Stack: " + ex.StackTrace;
                Trace.WriteLine(errMsg);
                WriteErrorEvent(errMsg);
                retVal = 0;
            }//end try
            return (retVal);
        }

        static bool ReadBool(String question) {
            while (true) {
                Console.WriteLine(question);
                String r = (Console.ReadLine() ?? "").ToLower();
                if (r == "y" || r == "yes" || r == "1")
                    return true;
                if (r == "n" || r == "no" || r=="0")
                    return false;
                Console.WriteLine("Please Select a Valid Option!!");
            }//end while
        }

        static void OnSqlRowsCopied(object sender, SqlRowsCopiedEventArgs e) { 
            Trace.WriteLine(String.Format("-- [{1}] Copied {0} rows.", e.RowsCopied, currentTableName));
        }

        private static string s(object o){
            return (Convert.IsDBNull(o) ? "" : Convert.ToString(o));
        }

        private static string _drToColSql(DataRow dr){
            string colName = s(dr["COLUMN_NAME"]);
            string ret = "[" + colName + "] ";
            string typeName = ((string)s(dr["TYPE_NAME"])).ToLower();
            switch(typeName){
                case "char":
                    ret += "CHAR(" + s(dr["LENGTH"]) + ")";
                    break;
                case "byte":
                    ret += "CHAR(" + s(dr["PRECISION"]) + ")";
                    break;
                case "text":
                    ret += "VARCHAR(" + s(dr["PRECISION"]) + ")";
                    break;
                case "date":
                    ret += "DATE";
                    break;
                case "time":
                    ret += "TIME(7)";
                    break;
                case "double":
                    ret += "DECIMAL(16,2)"; // + c(dr["PRECISION"]) + "," + c(dr["LENGTH"]) + ")";
                    break;
                case "usmallint":
                case "smallint":
                    ret += "SMALLINT";
                    break;
                case "utinyint":
                case "tinyint":
                    ret += "TINYINT";
                    break;
                case "identity":
                case "integer":
                    ret += "BIGINT";
                    break;
                case "smallidentity":
                case "short":
                    ret += "INT";
                    break;
                case "longvarchar":
                case "memo":
                    ret += "TEXT";
                    break;
                case "checkbox":
                    ret += "BIT";
                    break;
                case "real":
                    ret += "REAL";
                    break;
                default:
                    //this was an unexpected column, figure out what happened
                    Trace.WriteLine("ERROR - Column '" + colName + "' Details: ");
                    Trace.WriteLine("\tCOLUMN_NAME: " + s(dr["COLUMN_NAME"]));
                    Trace.WriteLine("\tTYPE_NAME: " + s(dr["TYPE_NAME"]));
                    Trace.WriteLine("\tDATA_TYPE: " + s(dr["DATA_TYPE"]));
                    Trace.WriteLine("\tLENGTH: " + s(dr["LENGTH"]));
                    Trace.WriteLine("\tPRECISION: " + s(dr["PRECISION"]));
                    Trace.WriteLine("\tSCALE: " + s(dr["SCALE"]));
                    Trace.WriteLine("\tNULLABLE: " + s(dr["NULLABLE"]));
                    throw new Exception("Unexpected data type: " + typeName);
            }

            if(s(dr["NULLABLE"])=="1"){
                ret += " NULL"; 
            }

            return ret;
        }

        private static bool CreateTableInDatabase(DataTable dtSchemaTable, string tableOwner, string tableName, SqlConnection sqlConn) {
            // Generates the create table command.
            string ctStr = "CREATE TABLE [" + tableOwner + "].[" + tableName + "](\r\n";
            for (int i = 0; i < dtSchemaTable.Rows.Count; i++)
            {
                ctStr += _drToColSql(dtSchemaTable.Rows[i]);
                if (i < dtSchemaTable.Rows.Count)
                    ctStr += ",";
                ctStr += "\r\n";
            }
            ctStr += ")";

            // Emit SQL statement
            Trace.WriteLine("-".PadLeft(30, '-'));
            Trace.WriteLine(ctStr + Environment.NewLine);

            // Runs the SQL command to make the destination table.      
            using(SqlCommand command = sqlConn.CreateCommand()){
                command.CommandText = "IF OBJECT_ID('dbo." + tableName + "', 'U') IS NOT NULL DROP TABLE dbo." + tableName;
                command.ExecuteNonQuery();
                command.CommandText = ctStr;
                command.ExecuteNonQuery();
            }
            return true;
        }

        private static bool WriteErrorEvent(string errMsg){
            const string sSource = "PervasiveOdbcSync";
            const string sLog = "Application";
            try{
                if (!EventLog.SourceExists(sSource))
                    EventLog.CreateEventSource(sSource,sLog);
                EventLog.WriteEntry(sSource, errMsg);
                EventLog.WriteEntry(sSource, errMsg, EventLogEntryType.Error, 128);
                return true;
            }catch(Exception ex){
                Trace.WriteLine("Unable to write error to event log. Reason: " + ex.Message);
                return false;
            }
        }

    }
}

您需要将 System.Diagnostics.ConsoleTraceListener 添加到 app.config 文件中。这样您就可以看到正在输出的所有内容。如果您还添加了 System.Diagnostics.TextWriterTraceListener,您可以使应用程序也将所有内容输出到日志文件。

于 2014-11-07T18:54:46.783 回答
0

在我也安装了 SQL Server 2008 R2 的 PSQL v11 机器上,我没有在 SQL Server 导入和导出向导的“数据源”对话框中看到“普遍的 ODBC 引擎接口”。我确实看到了“Pervasive PSQL OLEDB Provider”和“Pervasive Provider, release v4.0”(以及 3.5 和 3.2)。The Pervasive Provider 是一个 ADO.NET 提供程序。我确实看到了“.Net Framework Data Provider for ODBC”,如果我为 Pervasive DSN(如 DEMODATA)输入了 DSN 名称,它就可以工作。

于 2013-02-26T01:31:28.617 回答