SQL SMO:Как получить путь к имени физического файла базы данных?
-
19-08-2019 - |
Вопрос
Я пытаюсь вернуть физический путь к файлам mdf/ldf базы данных.
Я попробовал использовать следующий код:
Server srv = new Server(connection);
Database database = new Database(srv, dbName);
string filePath = database.PrimaryFilePath;
Однако это вызывает исключение: «database.PrimaryFilePath» выдало исключение типа «Microsoft.SqlServer.Management.Smo.PropertyNotSetException» - даже несмотря на то, что база данных, с которой я запускаю это, существует, и ее файл mdf находится в c:\ Программные файлы\Microsoft SQL Server\MSSQL.1\MSSQL
Что я делаю не так?
Решение
Обычно проблема заключается в том, что свойство DefaultFile имеет значение null.Файл данных по умолчанию — это место, где файлы данных хранятся на экземпляре SQL Server, если иное не указано в свойстве FileName.Если не указано другое местоположение по умолчанию, свойство вернет пустую строку.
Таким образом, это свойство ничего не возвращает (пустую строку), если вы не установили местоположение по умолчанию.
Обходной путь – проверить свойство DefaultFile. Если оно возвращает пустую строку, используйте SMO для получения основной базы данных, а затем используйте свойство Database.PrimaryFilePath для получения местоположения файла данных по умолчанию (поскольку оно не изменилось).
Поскольку вы говорите, что проблема связана с вашим PrimaryFilePath:
- Подтвердите, что ваше соединение открыто
- Подтвердите, что другие объекты доступны
Другие советы
Вот как я это делаю, подготовленный для нескольких имен файлов. Откройте файл database.LogFiles, чтобы получить тот же список имен файлов журнала:
private static IList<string> _GetAttachedFileNames(Database database)
{
var fileNames = new List<string>();
foreach (FileGroup group in database.FileGroups)
foreach (DataFile file in group.Files)
fileNames.Add(file.FileName);
return fileNames;
}
Server srv = новый сервер (соединение); DatabaseCollection dbc = svr.Databases; База данных базы данных = dbc [& Quot; dbName & Quot;]; строка filePath = database.PrimaryFilePath;
Я думаю, что самый простой подход - запустить скрипт sql на экземпляре сервера sql, который всегда будет возвращать вам правильные данные и пути к файлам журналов. Следующий sql сделает свое дело
SELECT
db.name AS DBName,
(select mf.Physical_Name FROM sys.master_files mf where mf.type_desc = 'ROWS' and db.database_id = mf.database_id ) as DataFile,
(select mf.Physical_Name FROM sys.master_files mf where mf.type_desc = 'LOG' and db.database_id = mf.database_id ) as LogFile
FROM sys.databases db
order by DBName
Вы все еще можете выполнить этот sql, используя SMO, если хотите, который вернет вам набор данных, а затем вы сможете извлечь эту информацию.
var result = new List();
var server = new Server( serverInstanceName );
var data = server.Databases[ "master" ].ExecuteWithResults(sql);
foreach ( DataRow row in data.Tables[ 0 ].Rows )
result.Add( new DatabaseInfo( row[ "DBName" ].ToString(), row[ "DataFile" ].ToString(), row[ "LogFile" ].ToString() ) );
return result;
Если вы будете использовать этот фрагмент, то обязательно создайте класс DatabaseInfo, в котором будет храниться информация, возвращенная из экземпляра сервера Sql.
using Smo = Microsoft.SqlServer.Management.Smo;
public string GetDataBasePath(string strDatabaseName)
{
ServerConnection srvConn = new ServerConnection();
srvConn.ConnectionString = "<your connection string goes here>";
Server srv = new Server(srvConn);
foreach (Smo.Database db in srv.Databases)
{
if (string.Compare(strDatabaseName, db.Name, true) == 0)
{
return db.PrimaryFilePath;
}
}
return string.Empty;
}