長々と申し訳ありませんが、情報が少なすぎる質問がたくさんあります...最初の数行で誰かが私のエラーを見つけたら、私は喜んで...
SQL Server 2008 R2 データベースを使用していますが、C# SqlConnection を介して接続するときに正しい動作であると思われるものを取得できません。
Visual C# 2010 Express でビルドされた 2 つの C# アプリケーションがあります。
- 1 つはデータのインポート/エクスポート/レポートおよび閲覧用
- 複雑な処理を行うためのもの
これはすべて、すべての更新などを含むWindows 7上にあります...
これら 2 つのアプリケーションのそれぞれで使用されるテーブルの一部は共有共通テーブルであり、他のテーブルは分離しておく必要があります。両者の間でデータを変換および転送できるようにする必要があるため、これらすべてを 1 つのデータベースに保持したいと考えています。
ある程度の分離を維持するために、次のように 2 つのスキーマ、2 つのユーザー、2 つのロール、および 2 つのログインを作成しました。
CREATE LOGIN [Import_User] WITH PASSWORD=N'*****'
CREATE LOGIN [Engine_User] WITH PASSWORD=N'*****'
CREATE USER [Import_User] FOR LOGIN [Import_User] WITH DEFAULT_SCHEMA=[Import_Schema]
CREATE USER [Engine_User] FOR LOGIN [Engine_User] WITH DEFAULT_SCHEMA=[Engine_Schema]
CREATE ROLE [Import_Role] AUTHORIZATION [dbo]
CREATE ROLE [Engine_Role] AUTHORIZATION [dbo]
EXEC('CREATE SCHEMA [Import_Schema] AUTHORIZATION [Import_User]')
EXEC('CREATE SCHEMA [Engine_Schema] AUTHORIZATION [Engine_User]')
-- Import role permissions on the Import schema
GRANT EXECUTE, DELETE, INSERT, SELECT, UPDATE, REFERENCES ON SCHEMA::[Import_Schema] TO [Import_Role]
-- Engine_Role permissions on the engine schema
GRANT EXECUTE, DELETE, INSERT, SELECT, UPDATE, REFERENCES ON SCHEMA::[Engine_Schema] TO [Engine_Role]
EXEC sp_addrolemember N'Import_Role', N'Import_User'
EXEC sp_addrolemember N'Engine_Role', N'Engine_User'
GRANT CONNECT TO [Import_User]
GRANT CONNECT TO [Engine_User]
次に、各スキーマに、各ロールに適したテーブルとストアド プロシージャをいくつか作成します。エンジン スキーマにはおそらく 20 のテーブルがあり、インポート スキーマには 30 程度のテーブルがあります。これらのいくつかは、2 つのスキーマで非常に似ていますが、まったく同じではありません。
CREATE TABLE [Engine_Schema].[Problem](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](50) NOT NULL,
[Description] [varchar](max) NULL,
CONSTRAINT [PK_Status] PRIMARY KEY CLUSTERED ( [ID] ASC )
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCK = ON) ON [PRIMARY])
ON [PRIMARY]
CREATE TABLE [Import_Schema].[Problem](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](50) NOT NULL,
[Client] [varchar](50) NOT NULL,
[Description] [varchar](max) NULL,
CONSTRAINT [PK_Status] PRIMARY KEY CLUSTERED ( [ID] ASC )
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCK = ON) ON [PRIMARY])
ON [PRIMARY]
SSMSを介してこれら2つのログインを使用してチェックすると、これはすべて正常に機能するようです.各ログインは、私が期待するテーブルとSPを正確に認識します. いずれの場合も、スキーマ プレフィックスを使用する必要なく、SSMS 内でクエリと USP を実行できます。これは、これらの接続が、ログイン/ユーザーごとに設定した既定のスキーマを使用するためです。「sa」としてログインすると、もちろん、両方のスキーマのすべてを見ることができます。
私の C# コードでは、次のようにデータベースに接続します。
SqlConnection dbConnection = new SqlConnection(""server=laptop; database=test; user id=Engine_User; password=*****; Trusted_Connection=yes; connection timeout=30");
dbConnection.Open();
次に、次のようにデータベース テーブルを直接クエリしようとします。
using (SqlCommand cmdSelectProblems = new SqlCommand()) {
cmdSelectProblems.Connection = dbConnection;
cmdSelectProblems.CommandText = "Select ID, Name from Problem order by Name";
DataTable dataTableProblems = new DataTable();
using (SqlDataAdapter dataAdapterProblems = new SqlDataAdapter(cmdSelectProblems)) {
dataAdapterProblems.Fill(dataTableProblems);
...
または、次のようなストアド プロシージャの 1 つを使用することもできます。
using (SqlCommand cmd = new SqlCommand()) {
cmd.Connection = dbConnection;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "SelectProblems";
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
da.Fill(_problemsTable);
}
しかし、これらの例のように C# コードで接続を使用しようとすると、次のようなエラーが発生します。
Invalid object name 'Problem'
また
Could not find stored procedure 'SelectProblems'
データベース内の同じ DB オブジェクトにアクセスするには、明示的なスキーマ プレフィックスを使用する必要があるようです。スキーマ プレフィックスが明示的に含まれているため、テストした限り、C# コードからすべてが機能するため、直接テーブル クエリを次のように変更します。
cmdSelectProblems.CommandText = "Select ID, Name from [Engine_Schema].Problem order by Name";
または、次のようなスキーマ プレフィックスを使用して USP にアクセスしてみてください。
cmd.CommandText = "[Engine_Schema].SelectProblems";
その後、すべてが正常に機能します。
明示的なスキーマ名を使用することがベスト プラクティスであることはわかっていますが、C# とストアド プロシージャの両方で、それらのスキーマ プレフィックスを使用せずに記述された大量のコードがあります。SqlConnection
C#クエリが、定義して使用しているログインの既定のスキーマを尊重するようにできれば、非常に簡単になります。これは私が設定した方法でうまくいくはずですが、どこかで何かを見逃したに違いないと思います。
私はこれまでに 2 日間を無駄にしましたが、読んだ限りでは、これはすべて機能するはずです。