質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

3回答

6294閲覧

C#の「connection.Open();」の例外について

d_neko

総合スコア108

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2020/01/12 01:40

下のコードは
https://docs.microsoft.com/ja-jp/dotnet/api/system.data.sqlclient.sqlconnection.begintransaction?view=netframework-4.8
のページにあるコードの一部です。

質問は、「←★★★★ここ」についてです。

もし、データベースに繋がらないとき、例外が発生すると思うのですが、
その例外ためにtry・catchで囲まないのでしょうか。

なぜ疑問に思ったかというと、昔なんかでtry・catchの説明(たぶんphp)で、
ファイルのオープンが例に上がっているのをみたからです。
私にとって、ファイルのオープンもデータベースの接続も同じようなものなので疑問に思いました。。

private static void ExecuteSqlTransaction(string connectionString) { using (SqlConnection connection = new SqlConnection(connectionString)) { connection.Open();←★★★★ここ SqlCommand command = connection.CreateCommand(); SqlTransaction transaction; // Start a local transaction. transaction = connection.BeginTransaction("SampleTransaction"); // Must assign both transaction object and connection // to Command object for a pending local transaction command.Connection = connection; command.Transaction = transaction; try {

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

もし、データベースに繋がらないとき、例外が発生すると思うのですが、その例外ためにtry・catchで囲まないのでしょうか。

catch して何ができるのでしょうか?

予測できないもしくは予測はできても何の対応もできない「例外」(例えば DB サーバーダウン)が発生した場合は、ユーザーがそのまま作業を続けて事態を悪化させないためにも、例外をランタイムに拾わせてアプリケーションを停止させるべきです。

参考にしている記事のコードは catch (Exception ex) と Exception をキャッチして例外を握りつぶしていますが、それは感心しません(catch してログを取って即 throw するということなら Exception を catch するのもアリだと思いますが)。

RollBack するという目的ならほかにもっとマシな手段があります。ユーザーへの通知が必要なら集約的例外処置という手段を取るべきです。

上記の詳しい話は以下の記事に書いてありますので一読されることをお勧めします。

NETの例外処理 Part.1
https://blogs.msdn.microsoft.com/nakama/2008/12/29/net-part-1/

.NETの例外処理 Part.2
https://blogs.msdn.microsoft.com/nakama/2009/01/02/net-part-2/

記事の内容を簡単にまとめると:。

(1) 予測可能で正しい業務フローに戻すことができる「業務エラー」(例:ユーザーの入力間違い)と、予測できないもしくは予測はできても何の対応もできない「例外」(例:DB サーバーダウン)を区別して対処。

(2) 「例外」はランタイムに拾わせてアプリケーションを停止させる。

(3) よほどのことがない限り try-catch は書かない。

(4) キャッチせざるを得ない場合でも Execption はキャッチしない。(範囲を絞る。例えば DB 関係の例外で予測される SqlException に限定して catch するとか)

(5) 間違って補足してしまった例外は throw する。(注:catch ブロックでキャッチした例外を throw するとスタックトレースが途切れるので単に throw と書く)

(6) ユーザーへの通知が必要なら、集約的例外処置を利用する。

あと、.NET 4 からは破損状態例外は catch できなくなっているそうですが、「それでも Catch (Exception e) を使用するのはよくない」ということについては以下の記事を見てください。

破損状態例外を処理する
https://docs.microsoft.com/ja-jp/archive/msdn-magazine/2009/february/clr-inside-out-handling-corrupted-state-exceptions

投稿2020/01/12 03:33

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

d_neko

2020/01/12 05:52

詳しい説明ありがとうございます。 リンク先を見ると、かなり難しそうなので、今からじっくり読もう思います。 >(3) よほどのことがない限り try-catch は書かない。 try-catchって書かなくていいものなのですか。 書かなければいけないものだと思っていました。 だから、try-catch について疑問に思ったので、本当に知りたいのはRollBackです。 >RollBack するという目的ならほかにもっとマシな手段があります。 だから、こちらの方が本当は聞きたいです。
退会済みユーザー

退会済みユーザー

2020/01/12 06:13 編集

紹介した記事を読んでください。上のあなたのコメントの疑問にすべて答えてくれるはずです。読んでも分からなかったということなら質問してください。RollBack の話は Part 2 に出ています。
guest

0

例外処理をどうすべきかというのは置いておいて、

サンプルはあくまでサンプルです。
マイクロソフトが提示しているサンプルだからといって、全ての例外に対して対応しているわけではありません。

投稿2020/01/12 05:34

YAmaGNZ

総合スコア10258

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

d_neko

2020/01/12 05:53

マイクロソフトが提示しているサンプルだから、正しく模範的な書き方だと思っていました。
len_souko

2020/01/12 06:31

サンプルの目的にもよるでしょう そもそも起こりうる例外はメソッドの解説に書いてあります そして、一般的にサンプルは何かの説明に付随するものなので、説明対象の内容以外のことを長々と書くと分からなくて見ている人はどこを見ればいいのかわかりません そうなるとサンプルの目的を果たせなくなるでしょう そのため、説明対象以外の内容は記述しません ごみ箱で「ペットボトル」と書いているところには缶や瓶や燃えるごみはダメとかいちいち書いていないのと同じです
guest

0

connection.Open();

で、例外が発生する可能性はあります。(接続がうまくいかなかった場合のSqlExceptionや、connectionStringの値が不正だったり、既にそのconnectionStringで接続済みだったりした場合のInvalidOperationException等が発生する可能性があります)

それをExecuteSqlTransaction関数の中でtry-catchしていないのは、catchしても何もできない(SqlServerに接続できないので、SqlServerの操作は出来ませんから、せいぜい"接続できませんでしたぁ"と報告するぐらい)からでしょう。

そこで、「SqlServerに接続できなかったら例外を上げますので、後は宜しくね」という方針でコーディングして、外の関数から以下のような感じのtry-catchで使ってもらう仕様になっているのだと思います。

try { ExecuteSqlTransaction("xxxxx"); //引数はconnectionString ... ... } catch(exception ex) { ... }

投稿2020/01/12 02:56

coco_bauer

総合スコア6915

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

d_neko

2020/01/12 05:39

回答ありがとうございます。 >catchしても何もできない 接続できないって情報は、大切じゃないのでしょうか? 私がプログラムを作って、誰かが使ってエラーが出たとします。 すると、私に報告が入ります。 そこで、どんなエラーと聞くと、 「英語で書いてあってわからん」という返事が予想できます。 しかし、日本語で「たぶん、サーバーノのエラー (T△T)」とでも出るようにしていると、 答えは違うと思います。すると対応が早くできると思いますが違うのでしょうか。
coco_bauer

2020/01/12 06:11

接続できないって情報は、例外によって返されています。 SqlConnectionクラスのドキュメントは、https://docs.microsoft.com/ja-jp/dotnet/api/system.data.sqlclient.sqlconnection?view=netframework-4.8 等、日本語でかかれているものも多いです。 SqlConnection([直訳]SQL接続)のConnectionの意味を辞書やWebで確認できない方にプログラムを作らせているのは、大変ご苦労だと思います。 中学英語で躓いている人が適切な日本語の説明文を作れることを期待するのは、リスクが高くありませんか?
d_neko

2020/01/12 06:46

>中学英語で躓いている人 「連結のエラー」にしろってことでしょうか。 使う方は、エラーが出るものを作るやつが悪いです。 どんなエラーか質問しても、まともな答えなんて期待できません。 わざわざ顔文字を入れたのは、「そのエラーに顔文字があった?」って聞くためです。 「顔文字」があれば、自分が把握しているエラーということです。 「サーバー」としたのは、使う側の覚えている単語の一つだからです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問