SqlConnection忽略用户的默认架构

Tim*_*ick 5 c# schema default sqlconnection

道歉这么长,但我看到了太多的问题,其中包含的信息太少...如果有人在前几行中看到我的错误,我会很高兴...

我有一个SQL Server 2008 R2数据库,并且在通过C#SqlConnection连接时无法获得我认为应该是正确的行为。

我有两个使用Visual C#2010 Express构建的C#应用​​程序:

  • 一种用于数据导入/导出/报告和浏览
  • 一种用于做一些复杂的处理

这一切都在Windows 7上,具有所有更新等...

这两个应用程序中的每个应用程序使用的某些表是共享的公用表,而其他表则需要保持分开。由于我需要能够在双方之间转换和传输数据,因此我希望将所有这些都保存在一个数据库中。

为了保持一定程度的分离,我创建了两个模式,两个用户,两个角色和两个登录名,例如:

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]
Run Code Online (Sandbox Code Playgroud)

然后,在每个模式中创建适合每个角色的一些表并存储proc。引擎模式中可能有20个表,导入模式中可能有30个左右。其中一些在两个模式中非常相似,但并不完全相同,例如:

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]
Run Code Online (Sandbox Code Playgroud)

当我通过SSMS检查使用这两个登录名时,这一切似乎都正常工作-每个登录名都能准确看到我期望的表和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();
Run Code Online (Sandbox Code Playgroud)

然后我尝试像这样直接查询数据库表:

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);
    ...
Run Code Online (Sandbox Code Playgroud)

或者我可以尝试使用这样的存储过程之一:

using (SqlCommand cmd = new SqlCommand()) {
  cmd.Connection = dbConnection;
  cmd.CommandType = CommandType.StoredProcedure;
  cmd.CommandText = "SelectProblems";
  using (SqlDataAdapter da = new SqlDataAdapter(cmd))
    da.Fill(_problemsTable);
}
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试通过这些示例的C#代码使用连接时,会出现类似以下错误:

Invalid object name 'Problem'
Run Code Online (Sandbox Code Playgroud)

要么

Could not find stored procedure 'SelectProblems'
Run Code Online (Sandbox Code Playgroud)

我似乎需要使用显式架构前缀来访问数据库中的那些相同的DB对象。就已明确包含模式前缀的情况而言,就我所测试的而言,所有内容都可以从我的C#代码运行,因此将直接表查询更改为:

  cmdSelectProblems.CommandText = "Select ID, Name from [Engine_Schema].Problem order by Name";
Run Code Online (Sandbox Code Playgroud)

或尝试使用模式前缀访问USP,例如:

  cmd.CommandText = "[Engine_Schema].SelectProblems";
Run Code Online (Sandbox Code Playgroud)

然后一切正常。

现在,我知道使用显式架构名称是最佳实践,但是我在C#中和在不使用这些架构前缀的情况下编写的存储过程中都有大量代码。如果我可以使C#SqlConnection查询尊重已定义和使用的登录名的默认架构,它将更加简单。我相信这应该可以按我设置的方式很好地工作,但是我想我肯定在某处错过了一些东西。

到目前为止,我已经在此浪费了两天,而我所读的所有内容都表明这一切都应该起作用。

Ric*_*ing 3

服务器=笔记本电脑;数据库=测试;用户id=Engine_User;密码= * ;
Trusted_Connection=是;连接超时=30

这就是您的问题 - 您使用的是 Windows 身份验证而不是 SQL 身份验证。将连接字符串更改为Trusted_Connection=no,一切都应该正常。