0

私のアプリケーションは、データベースに依存する winform アプリです。アプリケーションの起動時に、サーバー上の SQL データベースに接続し、この情報を DataSet/DataTable に入れます。

何らかの理由でサーバー上のデータベースにアクセスできない場合、アプリケーションには組み込みのフェイルオーバーがあり、ローカル データベースから情報を取得します。

通常のシナリオでツールを起動すると、SQL データベースから読み取られ、サーバー上で更新されている場合 (別のスニペットがこれをチェックします)、ローカル データベースが最新であることを確認する必要があります。問題が始まります..(以下を参照)

この部分は正常に機能し、コンテキストとして追加されます。これは、SQL データベースに接続する場所です。

    public static DataSet dtsTableContents;
    public static DataTable CreateDatabaseSQLConnection()
    {
        try
        {
            string strSqlConnectionString = "Data Source=MyLocation;Initial Catalog=MyCatalog;User=MyUser;Password=MyPassword;";
            SqlCommand scoCommand = new SqlCommand();
            scoCommand.Connection = new SqlConnection(strSqlConnectionString);
            scoCommand.Connection.Open();
            string strQueryToTable = "SELECT * FROM " + strTableName;
            dtsTableContents = new DataSet();
            SqlCommand scmTableInformation = new SqlCommand(strQueryToTable, scnConnectionToDatabase);
            SqlDataAdapter sdaTableInformation = new SqlDataAdapter(scmTableInformation);
            scnConnectionToDatabase.Open();
            sdaTableInformation.Fill(dtsTableContents, strTableName);
            DataTable dttTableInformation = dtsTableContents.Tables[strTableName];
            scnConnectionToDatabase.Close();
            return dttTableInformation;
        }
        catch
        {
            return null;
        }
    }

このスニペットは、ローカル データベースから読み取るフェールオーバー メソッドの一部です...

この部分は正常に機能し、コンテキストとして追加されます - ここで MDB データベースに接続します

public static DataTable CreateDatabaseConnection()
    {
        try
        {
            string ConnectionString = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=MyLocation;Persist Security Info=True;JET OLEDB:Database Password=MyPassword;"
            odcConnection = new OleDbConnection(ConnectionString);
            odcConnection.Open();
            string strQueryToTable = "SELECT * FROM " + strTableName;
            DataSet dtsTableContents = new DataSet();
            OleDbCommand ocmTableInformation = new OleDbCommand(strQueryToTable, ocnConnectionToDatabase);
            OleDbDataAdapter odaTableInformation = new OleDbDataAdapter(ocmTableInformation);
            ocnConnectionToDatabase.Open();
            odaTableInformation.Fill(dtsTableContents, strTableName);
            DataTable dttTableInformation = dtsTableContents.Tables[strTableName];
            ocnConnectionToDatabase.Close();
            return dttTableInformation;
        }
        catch
        {
            return null;
        }
    }

私の CreateDatabaseSQLConnection() から、DataSet があります。この DataSet には、サーバー データベースからのすべての情報が含まれていることが確認されています。今、私はグーグルで調べていて、このコードを使用して、この記事に基づいてローカルデータベースを更新しようとしていることに気付きました: http://msdn.microsoft.com/en-us/library/system.data.common.dataadapter.update( v=vs.71).aspx

public static void UpdateLocalDatabase(string strTableName)
    {
        try
        {
            if (CreateDatabaseConnection() != null)
            {
                string strQueryToTable = "SELECT * FROM " + strTableName;
                OleDbDataAdapter odaTableInformation = new OleDbDataAdapter();
                odaTableInformation.SelectCommand = new OleDbCommand(strQueryToTable, odcConnection);
                OleDbCommandBuilder ocbCommand = new OleDbCommandBuilder(odaTableInformation);
                odcConnection.Open();
                odaTableInformation.Update(dtsTableContents, strTableName);
                odcConnection.Close();
            }
        }
        catch { }
    }

このスニペットはエラーなしで実行されますが、何も変更されていないようです。また、このステップを実行するのにかかる時間はミリ秒のようにかかり、これにはもっと時間がかかると思います.

SQL 接続から取得した DataSet を使用しています。この DataSet をローカル データベースに書き込もうとしています。

これは SQL 接続からの DataSet であり、これを OleDbAdapter を介して mdb 接続に書き込むことができないという事実でしょうか、それともここで明らかなことを見逃しているのでしょうか?

どんな助けでも大歓迎です。

ありがとう、

ケビン

4

3 に答える 3

1

外部データベースから内部バックアップへのストレート バックアップの場合

私はsdfとサーバーベースのSQLデータベースをいじっていましたが、うまくいきました..それは決して完成品ではありませんが、1つの列について、外部データベースから読み取ってから直接書き込むプログラムを持っています.約 15 行のコードでローカル .sdf に移動

            SqlConnection sqlCon = new SqlConnection( ExternalDatabaseConnectionString );
            SqlCeConnection sqlCECon = new SqlCeConnection( BackUpConnectionString );
            using ( sqlCon )
                {
                using ( sqlCECon )

                    {
                    sqlCon.Open( );
                    sqlCECon.Open( );
                    SqlCommand get = new SqlCommand( "Select * from [TableToRead]", sqlCon );
                    SqlCeCommand save = new SqlCeCommand( "Update [BackUpTable] set InfoColumn = @info where ID = @id", sqlCECon );
                    SqlDataReader reader = get.ExecuteReader( );
                    if ( reader.HasRows )
                        {
                        reader.Read( );
save.Parameters.AddWithValue("@id", reader.GetString(0));
                            save.Parameters.AddWithValue( "@info", reader.GetString( 1 ));
                            save.ExecuteNonQuery( );
                            }
                        }
                    }

データベースの 1 つの行に対して、1 つの列をバックアップすると、うまくいきます。ID のような何らかの自動インクリメント キーがあると思いますか?

于 2012-06-08T14:59:15.520 に答える
0

DataAdapter.Update(Method)を際限なく使用しようとした後、私はあきらめました。mdbの代わりにsdfファイルを使用することにしました。

データベースを更新する必要がある場合は、ローカルデータベースを削除し、同じ接続文字列を使用して新しいデータベースを作成します。次に、データセット内のテーブルをループし、そこから列名とタイプを読み取り、それに基づいてテーブルを作成します。

この後、データセットをループして、サーバーからの情報を入力したデータセットのコンテンツを挿入します。以下はコードです。これは概念実証としての「迅速で汚い」ですが、私のシナリオでは機能します。

public static void RemoveAndCreateLocalDb(string strLocalDbLocation)
    {
        try
        {
            if (File.Exists(strLocalDbLocation))
            {
                File.Delete(strLocalDbLocation);
            }
            SqlCeEngine sceEngine = new SqlCeEngine(@"Data Source= " + strLocalDbLocation + ";Persist Security Info=True;Password=MyPass");
            sceEngine.CreateDatabase();
        }
        catch
        { }
    }

public static void UpdateLocalDatabase(String strTableName, DataTable dttTable)
    {
        try
        {

            // Opening the Connection
            sceConnection = CreateDatabaseSQLCEConnection();
            sceConnection.Open();

            // Creating tables in sdf file - checking headers and types and adding them to a query
            StringBuilder stbSqlGetHeaders = new StringBuilder();
            stbSqlGetHeaders.Append("create table " + strTableName + " (");
            int z = 0;
            foreach (DataColumn col in dttTable.Columns)
            {
                if (z != 0) stbSqlGetHeaders.Append(", "); ;
                String strName = col.ColumnName;
                String strType = col.DataType.ToString();
                if (strType.Equals("")) throw new ArgumentException("DataType Empty");
                if (strType.Equals("System.Int32")) strType = "int";
                if (strType.Equals("System.String")) strType = "nvarchar (100)";
                if (strType.Equals("System.Boolean")) strType = "nvarchar (15)";
                if (strType.Equals("System.DateTime")) strType = "datetime";
                if (strType.Equals("System.Byte[]")) strType = "nvarchar (100)";

                stbSqlGetHeaders.Append(strName + " " + strType);
                z++;
            }
            stbSqlGetHeaders.Append(" )");
            SqlCeCommand sceCreateTableCommand;
            string strCreateTableQuery = stbSqlGetHeaders.ToString();
            sceCreateTableCommand = new SqlCeCommand(strCreateTableQuery, sceConnection);

            sceCreateTableCommand.ExecuteNonQuery();


            StringBuilder stbSqlQuery = new StringBuilder();
            StringBuilder stbFields = new StringBuilder();
            StringBuilder stbParameters = new StringBuilder();

            stbSqlQuery.Append("insert into " + strTableName + " (");

            foreach (DataColumn col in dttTable.Columns)
            {
                stbFields.Append(col.ColumnName);
                stbParameters.Append("@" + col.ColumnName.ToLower());
                if (col.ColumnName != dttTable.Columns[dttTable.Columns.Count - 1].ColumnName)
                {
                    stbFields.Append(", ");
                    stbParameters.Append(", ");
                }
            }
            stbSqlQuery.Append(stbFields.ToString() + ") ");
            stbSqlQuery.Append("values (");
            stbSqlQuery.Append(stbParameters.ToString() + ") ");

            string strTotalRows = dttTable.Rows.Count.ToString();

            foreach (DataRow row in dttTable.Rows)
            {
                SqlCeCommand sceInsertCommand = new SqlCeCommand(stbSqlQuery.ToString(), sceConnection);
                foreach (DataColumn col in dttTable.Columns)
                {
                    if (col.ColumnName.ToLower() == "ssma_timestamp")
                    {
                        sceInsertCommand.Parameters.AddWithValue("@" + col.ColumnName.ToLower(), "");
                    }
                    else
                    {
                        sceInsertCommand.Parameters.AddWithValue("@" + col.ColumnName.ToLower(), row[col.ColumnName]);
                    }
                }
                sceInsertCommand.ExecuteNonQuery();
            }
        }
        catch { }
    }
于 2012-06-08T11:51:19.233 に答える
0

static最初のステップは、メソッドとフィールドへの依存を減らすことだと思います。

メソッドを見ると、そのメソッドで使用されているUpdateLocalDatabaseものを渡していることがわかりますが、 ( ) を呼び出すメソッドは、同じ名前の別のグローバル静的変数を参照しています。ほとんどの場合、2 つの変数には異なる値が含まれており、それらが同じ変数ではないことがわかりません。strTableNameUpdateLocalDatabaseCreateDatabaseConnectionstrTableName

dtsTableContentsまた、グローバルな静的データセットを書き出そうとしていますが、実際にUpdateLocalDatabaseそれを見るとCreateDatabaseConnection、実際にはその変数のローカルバージョンが作成されます-再び、同じ名前の2つの変数があり、1つはグローバルでもう1つはローカルです。

の 2 つの変数が問題であると思われますdtsTableContents

繰り返しになりますが、静的メソッドや変数を持たないようにし、ここで行っていることについては、グローバル変数を使用しないようにすることをお勧めします。また、メソッドのリファクタリングや名前の変更を行って、実際に行っていることにより一致するようにします。

于 2012-05-28T16:48:00.687 に答える