如果服务器上的一个数据库没有我用来创建SMO服务器连接的SQL用户,则SMO的Server.Databases将引发异常。
如果使用本地SQL 2017实例,我不会出现相同的错误。
例如:
我有一个名为'myazuresqlserver.database.windows.net'的SQL Azure服务器
创建登录名:
使用PASSWORD ='ThisIsMySecretPassword'创建登录登录测试
创建2个数据库,DB1和DB2。
在DB1中创建用户“测试用户”,但不 DB2:
为登录testlogin创建用户testuser
然后,使用C#和SMO,我无法使用testlogin登录凭据获得该服务器的数据库列表-发生异常。
static void Main(string[] args)
{
string[] names = GetDatabaseNames("myazuresqlserver.database.windows.net");
}
public static string[] GetDatabaseNames(string serverName)
{
ServerConnection connection = new ServerConnection(serverName, "testuser", "ThisIsMySecretPassword");
var server = new Server(connection);
return (from Database database in server.Databases
where !database.IsSystemObject && !database.IsDatabaseSnapshot
select database.Name
).ToArray();
}
例外是:
SqlException: The server principal "testlogin" is not able to access the database "DB2" under the current security context.
Cannot open database "DB2" requested by the login. The login failed. Login failed for user 'testlogin'.
我希望不会引发任何异常,而是Server.Databases仅包含提供的凭据有效的数据库-这似乎是本地SQL 2017实例的行为。
答案 0 :(得分:1)
我遇到了同样的问题。好像完全尝试查看Server.Database都会导致枚举,并且这样做会查看数据库属性-用户可能没有权限查询的属性。立即引发异常。
我最终使用了另一种技术来获取数据库列表。我只是触发了一个sql查询:
SELECT name FROM sys.databases WHERE name NOT IN ('master', 'tempdb', 'model', 'msdb');
要使上述查询生效,用户必须具有访问master数据库的权限。这是我的代码块:
Dim Server As Server = New Server(New ServerConnection("myserver.server.net", "testlogin", "password"))
Dim databaseList As New DataTable
databaseList.Columns.Add("Name")
If Server.Edition = "SQL Azure" Then
Dim SQLReader As SqlClient.SqlDataReader = Nothing
Try
SQLReader = Server.ConnectionContext.ExecuteReader("SELECT name FROM sys.databases WHERE name NOT IN ('master', 'tempdb', 'model', 'msdb');")
Do While SQLReader.Read = True
databaseList.Rows.Add(Manager.Database.Sanitise(SQLReader, "name").ToString)
Loop
SQLReader.Close()
Catch ex As Exception
MsgBox(ex.Message)
Finally
If Not SQLReader Is Nothing Then
SQLReader.Close()
End If
End Try
End If