sql-server - 使用 SQL CLR 的 VS2013 数据库项目 - 对对象 [服务器名\用户名](数据库所有者)的未解析引用

标签 sql-server visual-studio sqlclr

我正在 VS2013 中开发一个数据库项目,其中包含一个 C# SQL CLR 存储过程。

程序集所有者是 [servername\User123]
数据库所有者也是 [servername\User123] (作为数据库所有者,该用户显然已经存在于服务器上。我通过注释掉 SQL CLR 过程中的代码并发布来成功发布数据库,之后发生以下情况我取消注释掉该代码。)

如果我尝试在 VS 中构建项目,则会收到错误:

Error   1   SQL71501: Assembly: [DatabaseProject] has an unresolved reference to object [servername\User123].   

...引起的:

CREATE ASSEMBLY [DatabaseProject] AUTHORIZATION [servername\User123]
FROM 0x4D5A90000300000004000000FFFF0000B8000etcetcetcetc
WITH PERMISSION_SET = EXTERNAL_ACCESS
GO

因此,如果在 VS 中我在\Security 文件夹中添加创建用户脚本:

CREATE USER [servername\User123] FOR LOGIN [servername\User123] WITH DEFAULT_SCHEMA = dbo
GO
GRANT CONNECT TO [servername\User123]

然后我就可以构建该项目。

但是,如果我随后尝试发布数据库,则会收到错误:

Creating [servername\User123]...
(47,1): SQL72014: .Net SqlClient Data Provider: Msg 15063, Level 16, State 1, Line 1 The login already has an account under a different user name.
(47,0): SQL72045: Script execution error.  The executed script:
CREATE USER [servername\User123] FOR LOGIN [servername\User123];
An error occurred while the batch was being executed.

有“正确”的方法来做到这一点吗?

最佳答案

此问题是由于对 SQL Server 如何将数据库“所有者”处理为数据库“主体”的简单误解所致。 “数据库所有者”的概念以两种不同的方式出现:

  1. 作为数据库级用户,其名称为dboprincipal_id1 。现在,服务器级别的登录映射到这个特定的用户(即“主体”)只是SID字段中的值的问题在sys.database_principals中:

    SELECT sdp.*
    FROM   [sys].[database_principals] sdp
    WHERE  sdp.[principal_id] = 1;
    

    此字段将映射到 sys.server_principals 中的 SID 字段:

    SELECT sdp.*, '---' AS [---], ssp.*
    FROM   [sys].[database_principals] sdp
    INNER JOIN [sys].[server_principals] ssp
            ON ssp.[sid] = sdp.[sid]
    WHERE  sdp.[principal_id] = 1;
    

    注意sys.database_principals中的以下字段:

    • 类型
    • 类型描述
    • authentication_type
    • authentication_type_desc

    查看您的数据库当前如何由 Windows 登录名拥有,请运行上面的查询(第二个查询 - 包含两个表的查询)。接下来,将数据库更改为 sa 所有。接下来,打开一个新的查询选项卡。最后,在这个新窗口中运行相同的查询(以便您可以轻松比较“之前”和“之后”的结果),确保密切关注上面提到的 4 个字段以及 sid 字段。 (请注意,可以在没有登录的情况下创建用户,并且这些用户显然不会出现在 JOIN 到 sys 的查询中.server_principals,但这个问题专门处理登录s)。

    从所有这些您应该看到,指定登录名作为数据库的“所有者”并没有,事实上,创建一个用户 对于登录:它仅更新dbo 用户的定义。因此,拥有该数据库的登录技术上确实存在于该数据库中,但始终使用dbo 名称而不是其实际名称。这就是您收到以下错误的原因:

    The login already has an account under a different user name.

  2. 作为数据库角色,数据库中的任何用户都可以添加到其中,以便获得这些权限。

修复:

  • \Security 文件夹中删除 CREATE USER 脚本。
  • 改用AUTHORIZATION [dbo]

关于sql-server - 使用 SQL CLR 的 VS2013 数据库项目 - 对对象 [服务器名\用户名](数据库所有者)的未解析引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29327912/

相关文章:

sql-server - AppDomain 已卸载

sql - 如果值为空,如何将值返回到 sqldatareader?

javascript - Visual Studio 2015 JavaScript Intellisense 异常行为

c# - Visual Studio 2015 中用于 Firebird 的 ADO.NET 数据提供程序

c# - 我的 vs2008 文本格式化插件非常慢

c# - 从 SQL Server 2008 R2 使用 GSM 调制解调器发送 SMS

sql-server - 在 64 位 SQL Server 上运行 32 位程序集

sql - 在左连接上返回不同的行数

sql - 简单的数据透视

sql - T-SQL 中的动态 WHERE 子句