LocalDB v14 создает неправильный путь для файлов mdf

34

Недавно я обновил LocalDB с версии 13 до 14 с помощью установщика SQL Server Express и этой инструкции . После установки я остановил существующий экземпляр по умолчанию (MSSQLLOCALDB) версии 13 и создал новый, который автоматически использовал ядро ​​сервера v14.0.1000.

Я часто использую LocalDB для тестов интеграции баз данных, т.е. в своих тестах xunit я создаю (временную) базу данных, которая удаляется по завершении теста. Начиная с новой версии, к сожалению, все мои тесты не пройдены из-за следующего сообщения об ошибке:

CREATE FILE обнаружена ошибка операционной системы 5 (доступ запрещен.) При попытке открыть или создать физический файл 'C: \ Users \ kepflDBd0811493e18b46febf980ffb8029482a.mdf'

Странно то, что целевой путь для файла mdf неверен, обратная косая черта отсутствует между C: \ Users \ kepfl и DBd0811493e18b46febf980ffb8029482a.mdf (что является случайным именем базы данных для одного теста). Базы данных создаются с помощью простой команды CREATE DATABASE [databaseName]- здесь ничего особенного.

В SSMS я вижу, что целевые расположения для данных, журнала и резервного копирования следующие:

Места назначения LocalDB

Однако, когда я пытаюсь обновить местоположение, я получаю другое сообщение об ошибке:

Сообщение об ошибке при попытке обновления

Как я могу обновить расположение по умолчанию, чтобы LocalDB снова мог создавать базы данных? Очевидно, что LocalDB неправильно совмещает каталог расположения по умолчанию и имя файла базы данных - есть ли запись реестра, которую я могу редактировать? Или что-нибудь еще?

Обновление после ответа Дуга и комментария Сепупика

В соответствии с этим вопросом Stackoverflow местоположение по умолчанию также должно изменяться через реестр. Однако, если я пытаюсь найти соответствующие ключи «DefaultData», «DefaultLog» и «BackupDirectory», я не могу найти их в своем реестре. SQL Server v14 переименовал эти разделы реестра или переместил эту информацию из реестра?

feO2x
источник
К вашему сведению, я также не могу обновить расположение баз данных по умолчанию при работе SSMS в режиме администратора.
feO2x
1
Пожалуйста, смотрите обновление в моем ответе. Эта ошибка была исправлена ​​по состоянию на CU6, выпущенный в середине апреля ..
Соломон Руцкий

Ответы:

21

ОБНОВИТЬ

В CU 6 для SQL Server 2017 эта ошибка была исправлена. Теперь можно успешно выполнить следующее:

CREATE DATABASE [CreateDatabaseTest];
DROP DATABASE [CreateDatabaseTest];

Проблема и тот факт, что она исправлена ​​в CU6, описаны в следующей статье базы знаний:
базы знаний: ИСПРАВЛЕНИЕ: ошибка «Доступ запрещен» при попытке создать базу данных в SQL Server 2017 Express LocalDB

Чтобы получить Накопительное обновление, перейдите на следующую страницу и возьмите верхнюю (т.е. последнюю) сборку, которая может быть новее, чем CU6, в зависимости от того, когда вы видите это:

Версии сборки SQL Server 2017


НИЖЕ ИНФОРМАЦИЯ, НАБЛЮДАЕМАЯ С SQL Server 2017 CU6 (выпущена 2018-04-17)

Отсутствие обратной косой черты в комбинированном имени «путь + файл», по-видимому, является ошибкой в ​​SQL Server 2017. Я сам столкнулся с этим. Я даже попытался отредактировать реестр, чтобы добавить DefaultDataстроку Value для C: \ Users \ MyAccountName \ в оба следующих ключа (3 пути по умолчанию отсутствуют ни в одном из ключей реестра LocalDB, которые я просматривал):

  • Компьютер \ HKEY_CURRENT_USER \ Программное обеспечение \ Microsoft \ Microsoft SQL Server \ UserInstances \ {some-GUID-value}
  • Компьютер \ HKEY_LOCAL_MACHINE \ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ \ Microsoft \ Microsoft SQL Server \ MSSQL14E.LOCALDB \ MSSQLServer

И да, я завершил работу и снова запустил экземпляр LocalDB в обеих попытках.

Однако я не уверен, что неспособность изменить пути по умолчанию является ошибкой, поскольку это может быть просто плохая документация и плохая обработка ошибок вместе взятых. Я говорю это потому, что я только что попытался отредактировать расположение по умолчанию для SQL Server LocalDB версий 2014, 2016 и 2017, и все это привело к точно такой же ошибке, что само по себе странно из-за того RegCreateKeyEx(), что должно иметь дело с реестром и не файловая система.

Невозможность изменить путь вызывает сожаление из-за отсутствия обратной косой черты при создании новой базы данных без указания файлов для использования. Тем не менее, я смог создать новую базу данных, используя полный CREATE DATABASEсинтаксис следующим образом:

CREATE DATABASE [XXXXX]
 CONTAINMENT = NONE
 ON PRIMARY 
( NAME = N'XXXXX_sys', FILENAME = N'C:\Users\MyAccountName\XXXXX_sys.mdf',
  SIZE = 8192KB , MAXSIZE = UNLIMITED, FILEGROWTH = 65536KB ), 
 FILEGROUP [Tables] DEFAULT
( NAME = N'XXXXX_data', FILENAME = N'C:\Users\MyAccountName\XXXXX_data.ndf',
  SIZE = 8192KB , MAXSIZE = UNLIMITED, FILEGROWTH = 65536KB )
 LOG ON 
( NAME = N'XXXXX_log', FILENAME = N'C:\Users\MyAccountName\XXXXX_log.ldf',
  SIZE = 8192KB , MAXSIZE = UNLIMITED, FILEGROWTH = 65536KB )
 COLLATE Latin1_General_100_CS_AS_KS_WS_SC;
GO
Соломон Руцкий
источник
В нашей настройке базы данных мы применяем подход, который заключается в том, что если это соединение LocalDb, мы указываем путь к файлу MDF, как в вашем обходном пути. Но, по-видимому, нет необходимости указывать также название LDF или LOG ONраздел CREATE DATABASEинструкции. Файлы LDF создаются по умолчанию в том же месте, что и файл MDF. (Наш вариант использования LocalDb в основном предназначен для использования в автоматических тестах.)
tgharold
@tgharold Пожалуйста, смотрите обновление в верхней части моего ответа. Эта ошибка была совсем недавно исправлена ​​в новом патче CU6 :-).
Соломон Руцкий,
5

Я столкнулся с той же проблемой и нашел обходной путь, который не должен иметь никаких явных недостатков (если я что-то забыл, пожалуйста, исправьте меня) . Он основан на ответе Соломона, но без необходимости указывать абсолютный путь к файлам базы данных напрямую.

DECLARE @databaseName NVARCHAR(MAX) = 'MyDatabase'

DECLARE @dataFilePath NVARCHAR(MAX) = CAST(SERVERPROPERTY('InstanceDefaultDataPath') AS NVARCHAR) 
    + FORMATMESSAGE('\%s.mdf', @databaseName)

DECLARE @sql NVARCHAR(MAX) = FORMATMESSAGE(
    'CREATE DATABASE %s ON PRIMARY ( NAME = %s, FILENAME = ''%s'' )', 
    quotename(@databaseName), quotename(@databaseName), @dataFilePath
)

EXEC (@sql)

Он использует динамический sql и не совсем симпатичен, но он выполняет свою работу до тех пор, пока не будет официального решения проблемы.

Николай Дам Ларсен
источник
1
Интересный. Это может быть немного лучше , чтобы переместить 2 - ой QUOTENAMEна 2 - м парам из FORMATMESSAGEи поставить двойные кавычки путь к файлу: FORMATMESSAGE(N'CREATE DATABASE %s ON PRIMARY ( NAME = %s, FILENAME = "%s" )', QUOTENAME(@databaseName), QUOTENAME(@databaseName), @dataFilePath);. Но, похоже, работает так, как есть сейчас, поэтому +1 за этот подход. Все еще есть случай жестко кодировать имя или передавать путь: когда вы не хотите использовать USERPROFILEкорень. Но вы могли бы допустить это здесь и просто по умолчанию, InstanceDefaultDataPathесли @Path IS NULL. :-)
Соломон Руцкий,
Спасибо. Я отредактировал ответ с вашим предложением. Я согласен, что жесткое программирование абсолютного пути, безусловно, остается верным решением. Однако в нашем сценарии мы воссоздаем базу данных только во время автоматического тестирования, и мне нужно было убедиться, что она будет работать для всех моих коллег и сервера сборки, без необходимости координировать создание каждой папки по одному и тому же пути на их локальной машине. :-)
Николай Дам Ларсен
4

Я тоже сталкиваюсь с этой проблемой. Единственный обходной путь, который я нашел, - это предоставить доступ на запись c:\Users\каждому (или что-то в этом роде) и позволить ему создавать mdf-файлы там, где он хочет.

abatishchev
источник
1
Спасибо, это решило это и для меня! Это обходной путь - отстой, но он только на нашем локальном сервере сборки, поэтому мне не нужны дополнительные права пользователя.
Ханнес Саксенхофер
@HannesSachsenhofer: согласен, это отстой. Но команда разработчиков LocalDB пообещала, что они исправят эту ошибку в следующем выпуске исправлений.
Абатищев
Предоставление доступа на запись каждому кажется мне довольно плохим обходным путем
Рафаэль
@ Рафаэль: почему? У вас есть несколько пользователей на вашем Dev Dev? А кому ты не доверяешь?
Абатищев
2

Спасибо за ваше краткое объяснение этой проблемы. Я столкнулся с этим же вопросом вчера. Я до сих пор не нашел постоянного решения, но вот мой текущий обходной путь.

Я использую функцию Database.EnsureCreated () для создания базы данных.

Установите строку подключения, чтобы включить параметр « AttachDBFilename = ».

Server=(LocalDB)\\MSSQLLocalDB;Database=ExploreCalifornia;AttachDbFilename=.\\ExploreCalifornia.mdf;Trusted_Connection=True;MultipleActiveResultSets=true

Запустите приложение. Это сгенерирует ошибку:

Не удается прикрепить файл «. \ ExploreCalifornia.mdf» в качестве базы данных «ExploreCalifornia».

но это создаст базу данных.

После этого измените строку подключения и удалите AttachDBFilename = .

 Server=(localdb)\\MSSQLLocalDB;Database=ExploreCalifornia;Trusted_Connection=True;MultipleActiveResultSets=true

Я снова запустил приложение без ошибок и таблицы были созданы.

Дуг Абрахамсон
источник
Пара вопросов: во-первых, просто чтобы быть уверенным - вы изначально получали ошибку (доступ запрещен), и это решило это, верно? Второе - SQL Server Management Studio - единственное приложение, упомянутое IP, и это не похоже на то, что вы сделали оттуда - из какого приложения вы делали все это?
RDFozz
Спасибо за ваш ответ, но это не решает мою проблему. Мой тестовый код создает новую базу данных с простой CREATE DATABASE [databasename]функцией LocalDB, и это утверждение вызывает проблемы, так как LocalDB ошибочно объединяет каталог местоположений по умолчанию со случайно сгенерированным именем базы данных (см. Параграфы 3 и 4 моего вопроса). Мне нужен способ исправить местоположения по умолчанию, чтобы эта проблема конкатенации не возникала.
feO2x
В настоящее время я не могу создать базу данных с помощью SQL / DDL вообще. Не имеет значения, выполняю ли я оператор через SSMS, или из кода, или где-либо еще, потому что LocalDB всегда пытается создать базу данных непосредственно в каталоге Users (что совершенно неверно, в этом каталоге не разрешено существование файлов) ,
feO2x
1
Вы возможно ошиблись AttachDBFilename.
Тгарольд