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 неправильно поєднує каталог розташування за замовчуванням та ім'я файлу бази даних - чи є в реєстрі запис, який я можу редагувати? Або що-небудь ще?

Оновлення після відповіді Дуга та коментаря sepupic

Відповідно до цього питання Stackoverflow , розташування за замовчуванням також повинно бути змінено через реєстр. Однак якщо я спробую знайти відповідні клавіші "DefaultData", "DefaultLog" та "BackupDirectory", я не можу їх знайти у своєму реєстрі. Чи перейменував SQL Server v14 ці ключі реєстру чи перемістив цю інформацію з реєстру?


FYI, я також не можу оновити розташування за замовчуванням баз даних під час роботи SSMS в режимі адміністратора.
feO2x

1
Будь ласка, дивіться оновлення у моїй відповіді. Ця помилка була виправлена ​​станом на CU6, випущена в середині квітня ..
Соломон Руцький

Відповіді:


21

ОНОВЛЕННЯ

Станом на CU 6 для SQL Server 2017 цю помилку виправлено. Тепер можна успішно виконати такі дії:

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

Проблема та той факт, що вона виправлена ​​в CU6, задокументована у наступній статті KB:
FIX: Помилка "Доступ заборонено" при спробі створення бази даних у SQL Server 2017 Express LocalDB

Щоб отримати накопичувальне оновлення, перейдіть на наступну сторінку та перейдіть на верхню (тобто останню) збірку, яка може бути новішою, ніж CU6, залежно від того, коли ви бачите це:

Версії для складання SQL Server 2017


НИЖЧА ІНФОРМАЦІЯ ПРОБЛЕМИ ЯК SQL SERVER 2017 CU6 (Випущено 2018-04-17)

Відсутність зворотної косої риси у комбінованому імені Path + File, схоже, є помилкою у SQL Server 2017. Я просто натрапив на нього сам. Я навіть спробував редагувати Реєстр, щоб додати DefaultDataзначення рядка для C: \ Users \ MyAccountName \ в обох наступних ключах (3 шляху за замовчуванням відсутні в жодному з ключів реєстру LocalDB, який я переглянув):

  • Комп'ютер \ HKEY_CURRENT_USER \ Програмне забезпечення \ Microsoft \ Microsoft SQL Server \ UserInsances \ {деяке значення GUID}
  • Комп'ютер \ HKEY_LOCAL_MACHINE \ SOFTWARE \ 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-файли там, де він хоче.


1
Дякую, це вирішило це і для мене! Це вирішення проблеми, але це лише на локальному сервері побудови, тому я не переймаюся додатковими правами користувача.
Ганнес Саксенхофер

@HannesSachsenhofer: Я згоден, це відстійно. Але мені пообіцяла команда розробників LocalDB, що вони виправлять цю помилку у майбутньому випуску гарячих виправлень.
абатищев

Надання доступу на запис для всіх видається мені досить поганим вирішенням
Рафаель

@Raphael: Чому? У вас є кілька користувачів на вашій платформі Dev? А кому ви не довіряєте?
абатищев

2

Дякую за коротке пояснення цієї проблеми. Я вчора зіткнувся з цим самим питанням. Я досі не знайшов постійного рішення, але ось мій поточний шлях.

Я використовую функцію Database.EnsureCreate () для створення бази даних.

Встановіть рядок підключення для включення параметра " 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 - це єдиний додаток, згаданий IP, і це не схоже на щось, що ви робили звідти - з якої програми ви все це робили?
RDFozz

Дякую за вашу відповідь, але це не дуже вирішує мою проблему. Мій тестовий код створює нову базу даних із простою CREATE DATABASE [databasename]програмою щодо LocalDB, і саме ця заява викликає проблеми, оскільки LocalDB неправильно поєднує каталог розташування за замовчуванням з випадково згенерованим іменем бази даних (див. Пункти 3 та 4 мого запитання). Мені потрібен спосіб виправити розташування за замовчуванням, щоб ця проблема з конкатенацією не виникала.
feO2x

Наразі я взагалі не в змозі створити базу даних через SQL / DDL. Не має значення, чи запускаю я оператор через SSMS, або з коду, або деінде, тому що LocalDB завжди намагається створити базу даних безпосередньо в каталозі Користувачі (що абсолютно неправильно, жодні файли не дозволяють існувати в цьому каталозі) .
feO2x

1
Ви, можливо, неправильно написали AttachDBFilename.
tgharold
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.