カテゴリー別アーカイブ: DB

DbDataAdapter.DisposeはDbCommandオブジェクトをDisposeしない

大量にDbDataAdapter使うコードで、途中でFillできなくなって調べた結果です。

System.Data.Common.DbDataAdapterにはSystem.Data.IDbDataAdapterインターフェースの実装であるSelect/Insert/Update/DeleteCommandプロパティがあり、これらのプロパティにはSystem.Data.IDbCommand型のオブジェクトの設定/取得が可能です。

そして、DbDataAdapter.Disposeメソッドを呼び出しても、この4つのコマンドオブジェクトはDisposeされず、nullが設定されるだけです。したがって、各プロパティに設定したコマンドオブジェクトは、そのコマンドオブジェクトを生成する側で、明示的にDisposeしてやらないといけません。

[参照]
https://github.com/Microsoft/referencesource/blob/master/System.Data%2FSystem%2FData%2FCommon%2FDbDataAdapter.cs#L236

override protected void Dispose(bool disposing) { // V1.0.3300, MDAC 69629
    if (disposing) { // release mananged objects
        IDbDataAdapter pthis = (IDbDataAdapter) this; // must cast to interface to obtain correct value
        pthis.SelectCommand = null;
        pthis.InsertCommand = null;
        pthis.UpdateCommand = null;
        pthis.DeleteCommand = null;
    }
    // release unmanaged objects
    base.Dispose(disposing); // notify base classes
}

最初、どうしてこうなってるのかなーと思ったのですが、DbDataAdapterはあくまでAdapterであって、Compositionではないからかと納得しました。どういうことかというと、DbDataAdapterへの各コマンドの付け外しは自由自在なので、DbDataAdapterがコマンドオブジェクトの死活管理を行うことはできないんですよね。

ハマりかけてなるほどなぁという話でした。

「LocalDB インスタンスは壊れています。」の対処法

ひょんなことからこんなエラーが発生するようになってしまいました。

ログの名前:         Application
ソース:           SQLLocalDB 11.0
日付:            2013/11/29 17:01:40
イベント ID:       267
タスクのカテゴリ:      なし
レベル:           エラー
キーワード:         クラシック
ユーザー:          N/A
コンピューター:       ***********
説明:
LocalDB インスタンスは壊れています。エラーの詳細については、Windows アプリケーション イベント ログを参照してください。

“LocalDB インスタンスは壊れています。”で検索しても一向にヒットしないので、”LocalDB instance is”まで打ったところで“LocalDB instance is corrupted”がサジェストされて「これだ!」と。

んで、見つけました。

 Mick’s Breeze Blogs – Biztalk/Sharepoint/… – SQL 2012 LocalDB: LocalDB instance is corrupted–Fixed.

The Magic Juice – enter SqlLocalDB.exe

This guy is the admin tool of SQL LocalDB – so delving into the supported commands I could:

a) list all the known LocalDB instances

b) Delete an instance

c) Create an instance

So in short –

sqllocaldb delete “v11.0”

sqllocaldb create “v11.0”

というわけで、このコマンドをコマンドプロンプトから実行して無事復旧。いや~、焦りましたf(^^;

Accessから独自のtnsnames.oraでOracleにODBC接続する方法

管理者権限のないアカウントでWindowsを使うことになり、%OracleHome%\NETWORK\ADMIN\tnsnames.oraをいじれなくて困っていたのですが、次の方法でAccessから独自のtnsnames.oraを使ってODBC接続できることが分かりました。

 

ポイント

  • Access DBファイルと同じところに独自tnsnames.oraを作成する。
  • Access DBファイルと同じところにファイルデータソースを作成する。
  • 作成後は、Access DBファイルのみ他の場所に移動しても大丈夫。
  • ファイルデータソースやtnsnames.oraを移動させると接続できなくなる。

 

手順

1.独自のtnsnames.oraの作成

必要な内容を記述して任意のフォルダに配置します。ここではマイドキュメント(%USERPRIFILE%\Documents)に保存することにしましょう。

 

2.Access DBの作成

1.で作成したtnsnames.oraと同じフォルダにAccess DBを作成します。

 

3.ODBC接続

あとはAccessから接続するだけです。[外部データ]タブの[ODBC データベース]を選択します。

AccessのODBCデータベースボタン

「外部データの取り込み – ODBC データベース」ダイアログが開き、「データのインポート元とインポート先、またはリンク元とリンク先の選択」画面が表示されるので、目的とする方を選びます。今回は[リンク テーブルを作成してソース データにリンクする]を選びます。

外部データの取り込みダイアログ

「データ ソースの選択」ダイアログが表示されるので[新規作成]ボタンをクリックします。

データソースの選択ダイアログ

[データ ソースの新規作成」ダイアログが開くので、OracleのODBCドライバーを選択して、[次へ]ボタンをクリックします。

例ではOracle 11gのODBCドライバーを選択しているところです。

データソースの新規作成ダイアログ データソースのドライバー選択

任意の[データ ソース名]を入力して[次へ]ボタンをクリックします。

パスを省略すると、「マイ ドキュメント」に作成されます。

データソースの新規作成ダイアログ ファイルデータソース名入力

[完了]ボタンをクリックします。

データソースの新規作成ダイアログ 確認画面

「Oracle ODBC ドライバ接続」ダイアログが新たに開くので、サービス名に先ほど作成した独自のtnsnames.oraに記述したサービス名、あとは必要なユーザー名、パスワードを入力して[OK]ボタンをクリックします。

Oracle ODBC ドライバ接続-1回目

「データ ソースの選択」ダイアログに戻ると、今作成したデータソースの名前が[DNS 名]に設定されているので、そのまま[OK]ボタンをクリックします。

DSNファイル選択後のデータソースの選択ダイアログ

あとは、再び「Oracle ODBC ドライバ接続」ダイアログが開くので、必要なパスワードを入力して[OK]ボタンを押せば完了です。

Oracle ODBC ドライバ接続-2回目

 

知っている人には常識なのでしょうが、これで1日くらいはまったのでメモ。