by WebSurfer
2014年5月30日 16:37
SQL Server の接続文字列で Initial Catalog(データベース名)の指定は必要かという話を書きます。
MSDN ライブラリなどでは、SQL Server の既定のインスタンスまたは名前つきインスタンスに接続する場合の接続文字列(正確には SqlClient 接続文字列)の例として、Initail Catalog(もしくは Database)キーワードでデータベース名を指定するように書かれています。
具体例は下記のページを見てください。
Initial Catalog(もしくは Database)のない接続文字列の例は、自分が知る限りですが、見たことがないです。
なので、接続文字列にデータベース名の指定は必須かと思い込んでいましたが、ある機会に試してみたところ、そんなことはなかったです。
以下の条件が満足されれば、任意のデータベースからデータを取得できます。
-
SQL Server の既定のインスタンスまたは名前つきインスタンスが対象。(ユーザーインスタンスとか LacalDB など、.mdf ファイルを動的にアタッチするようなケースはダメです)
-
同一インスタンス内にある、静的にアタッチ済みのデータベースを対象とする。
-
接続文字列で指定したログイン権限で SQL Server による認証が通ってログインできること。
-
接続文字列にデータベース名の指定がない場合、もしくは指定されていてもそれとは異なるデータベースを対象とする場合は、データベース名を特定できるクエリを記述する。例えば、 [データベース名].[スキーマ名].[テーブル名] というように。
-
ログインしたユーザーが、目的のデータベースに対して必要な権限を持っている(すなわち、SQL Server によるユーザー承認が通る)。具体的には、先の記事 ユーザー権限の設定 に書いたような設定がしてあることが条件です。
ADO.NET のコードを使って説明した方が分かりやすいと思いますので、以下にサンプルをアップしておきます。説明はコメントに書きましたので見てください。
using System;
using System.Data.SqlClient;
class Program
{
static void Main(string[] args)
{
// Initial Catalog=PUBS でも NORTHWIND から取得できる。
// Initial Catalog の指定なしでも OK。下はその例。
// ただしクエリに DB 名の指定が必要。下の例を参照。
// Integrated Security=True まで省くとログインできない。
string connString1 =
"Data Source=tcp:papiko-pc;Integrated Security=True";
string query1 =
"SELECT CategoryID, CategoryName " +
"FROM [NORTHWIND].[dbo].[Categories];" +
"SELECT EmployeeID, LastName " +
"FROM [NORTHWIND].[dbo].[Employees]";
RetrieveMultipleResults(new SqlConnection(connString1), query1);
// Initial Catalog を指定すればクエリで DB 名の指定は不要(下
// の例では NORTHWIND に含まれる Categories テーブル)。
// ただし、titleauthor テーブルは PUBS に含まれるものなので、
// 下の例のようにクエリに DB 名の指定が必要。
string connString2 =
"Data Source=tcp:papiko-pc;Initial Catalog=NORTHWIND;" +
"Integrated Security=True";
string query2 =
"SELECT CategoryID, CategoryName FROM Categories;" +
"SELECT royaltyper, au_id FROM [PUBS].[dbo].[titleauthor]";
RetrieveMultipleResults(new SqlConnection(connString2), query2);
}
// MSDN ライブラリ「DataReader によるデータの取得」
// http://msdn.microsoft.com/ja-jp/library/haa3afyz.aspx
// NextResult による複数の結果セットの取得
static void RetrieveMultipleResults(
SqlConnection connection, string query)
{
using (connection)
{
SqlCommand command = new SqlCommand(query, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
while (reader.HasRows)
{
Console.WriteLine("\t{0}\t{1}", reader.GetName(0),
reader.GetName(1));
while (reader.Read())
{
Console.WriteLine("\t{0}\t{1}",
reader.GetInt32(0), reader.GetString(1));
}
// バッチ Transact-SQL ステートメントの結果を読み込む
// ときに、データリーダーを次の結果に進めます。
reader.NextResult();
}
}
}
}
よく分からないのは、上記のようなことができるのに、何のためにデータベース名を接続文字列に指定するかということです。
クエリを書くときにデータベース名を省略できるぐらいのメリットしか思い浮かびません。他に、コードファーストを利用する際 Initial Catalog に指定された名前でデータベースを作ってくれるということもあるそうですが。でも、そんな理由ではなさそうです。
接続プールが複数作られることになるのも無駄なような気がします。(Initial Catalog が違えばもちろん、キーワードを異なる順序で指定しただけでも接続プールは異なるとのこと。詳しくは MSDN ライブラリ SQL Server の接続プール (ADO.NET) を参照)
上のサンプルの結果からわかるように、接続プールは接続文字列で指定されるインスタンスに接続するためにあるだけで、インスタンス中にあるどのデータベースに接続するかは関知しないです。
それなのに、わざわざ接続文字列にデータベースを指定して、複数の接続プールを作る理由が分かりません。
そもそも、同じ接続プールで複数の異なるデータベースに接続するなどということはやってはいけないことで、好ましからざる副作用があるのでしょうか?
by WebSurfer
2012年7月24日 23:20
データベースに接続しようとして "初期化文字列の形式が使用に適合しません。index x で始まっています。"(実際には x には数字が入ります)というエラーメッセージが出ることがあります。
「使用」って何?、「index」って何?・・・って感じで意味不明ですが、原文(英文)は次のようになっていて、これなら意味が分ります。
"Format of the initialization string does not conform to specification starting at index x"
つまり、接続文字列の x 文字目(0 から数えて)以降が、仕様(使用ではなくて)に適合しないということです。要するに接続文字列が間違っているということです。
例えば、接続文字列で Initial Catalog=Northwind の設定を間違えて以下のようにしたとします。
Data Source=.\SQLEXPRESS;Initial Catalog='Northwind ...
そうすると、上の画像のように "初期化文字列の形式が使用に適合しません。index 25 で始まっています。" というエラーがでます。'Northwind は間違いで、その ' は最初の文字 Data の D を 0 から数えて 25 番目です。
.NET 4 になって、「使用」の間違いぐらいは「仕様」に直したかと思って、調べてみましたが、間違ったままでした。
ただし、接続文字列の間違��が問題ではなくて、レジストリキーの修正が必要という話もありますので注意してください。
データベースの接続が出来ません
7ac50791-abdb-4628-b8bc-7a6d119afb5f|6|1.3
Tags: 接続文字列
ADO.NET
by WebSurfer
2010年7月30日 12:36
SQL Server などの接続文字列は、ソース中にハードコーディングせず、Web アプリなら web.config ファイルに、Windows アプリなら Settings.settings ファイルに格納しておき、そこから取得します。
その接続文字列を取得するコードは以下のようになります。
Web アプリケーション
string connectionString =
ConfigurationManager.ConnectionStrings["MyDB"].ConnectionString;
Windows アプリケーション
string connectionString =
Properties.Settings.Default.MyDB;
上記で、MyDB は接続文字列を定義する際に自ら名づけた名前で、当然任意に別名をつけることができます。例えば MyDB と名づけると、web.config, Settings.settings ファイルの中では以下のようになります。
web.config
<connectionStrings>
<add name="MyDB"
connectionString="Data Source= ..."
providerName="System.Data.SqlClient" />
</connectionStrings>
Settings.settings
<Settings>
<Setting Name="MyDB" Type="(Connection string)" Scope="Application">
・・・中略・・・
</Setting>
</Settings>
正確に憶えていないので、その度に昔のコードを調べるという面倒なことをしていましたが、自分のブログの索引からも見つけられるように書いておきました。
ab19d292-c1dc-409b-883e-fec7eed6cd9a|1|5.0
Tags: 接続文字列
ADO.NET