LocalDB v14 tworzy niewłaściwą ścieżkę do plików mdf

34

Ostatnio zaktualizowałem LocalDB z wersji 13 do 14 za pomocą instalatora SQL Server Express i tej instrukcji . Po instalacji zatrzymałem istniejącą instancję domyślną (MSSQLLOCALDB) w wersji 13 i utworzyłem nową, która automatycznie używała silnika serwera v14.0.1000.

Często używam LocalDB do testów integracji bazy danych, tj. W moich testach xunit tworzę (tymczasową) bazę danych, która jest usuwana po zakończeniu testu. Od nowej wersji niestety wszystkie moje testy nie powiodły się z powodu następującego komunikatu o błędzie:

UTWÓRZ PLIK napotkał błąd systemu operacyjnego 5 (Odmowa dostępu.) Podczas próby otwarcia lub utworzenia pliku fizycznego „C: \ Users \ kepflDBd0811493e18b46febf980ffb8029482a.mdf”

Dziwne jest to, że ścieżka docelowa pliku mdf jest niepoprawna, brakuje ukośnika odwrotnego między C: \ Users \ kepfl i DBd0811493e18b46febf980ffb8029482a.mdf (która jest losową nazwą bazy danych dla pojedynczego testu). Bazy danych są tworzone za pomocą prostego polecenia CREATE DATABASE [databaseName]- tutaj nic specjalnego.

W SSMS widzę, że docelowe lokalizacje danych, dziennika i kopii zapasowej są następujące:

Lokalizacje docelowe LocalDB

Jednak gdy próbuję zaktualizować lokalizację, pojawia się kolejny komunikat o błędzie:

Komunikat o błędzie podczas próby aktualizacji

Jak mogę zaktualizować domyślne lokalizacje, aby LocalDB mógł ponownie tworzyć bazy danych? Oczywiste jest, że LocalDB nie łączy poprawnie domyślnego katalogu lokalizacji i nazwy pliku bazy danych - czy istnieje wpis rejestru, który mogę edytować? Albo coś innego?

Aktualizacja po odpowiedzi Douga i komentarzu sepupika

Zgodnie z tym pytaniem Stackoverflow domyślną lokalizację należy również zmienić za pośrednictwem rejestru. Jeśli jednak spróbuję znaleźć odpowiednie klucze „DefaultData”, „DefaultLog” i „BackupDirectory”, nie mogę ich znaleźć w moim rejestrze. Czy program SQL Server v14 zmienił nazwy tych kluczy rejestru lub przeniósł te informacje z rejestru?

feO2x
źródło
Do Twojej wiadomości, nie mogę również zaktualizować domyślnych lokalizacji bazy danych, gdy uruchomię SSMS w trybie administratora.
feO2x
1
Proszę zobaczyć aktualizację w mojej odpowiedzi. Ten błąd został naprawiony od CU6, wydany w połowie kwietnia ..
Solomon Rutzky

Odpowiedzi:

21

AKTUALIZACJA

Od CU 6 dla SQL Server 2017 ten błąd został naprawiony. Teraz można pomyślnie wykonać następujące czynności:

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

Problem i fakt, że został rozwiązany w CU6, jest udokumentowany w następującym artykule KB:
POPRAWKA: Błąd „Odmowa dostępu” podczas próby utworzenia bazy danych w SQL Server 2017 Express LocalDB

Aby uzyskać aktualizację zbiorczą, przejdź do następującej strony i pobierz najwyższą (tj. Najnowszą) kompilację, która może być nowsza niż CU6, w zależności od tego, kiedy ją zobaczysz:

Wersje kompilacji programu SQL Server 2017


PONIŻEJ INFORMACJI OBSOLETE AS OF SQL SERVER 2017 CU6 (Wydany 2018-04-17)

Brak odwrotnego ukośnika w połączonej nazwie Ścieżka + Plik wydaje się być błędem w SQL Server 2017. Właśnie na to wpadłem. Próbowałem nawet edytować Rejestr, aby dodać DefaultDataciąg Wartość C: \ Users \ MyAccountName \ w obu następujących kluczach (3 domyślne ścieżki nie znajdują się w żadnym z kluczy rejestru LocalDB, przez które przeglądałem):

  • Komputer \ HKEY_CURRENT_USER \ Software \ Microsoft \ Microsoft SQL Server \ UserInstances \ {some-GUID-value}
  • Komputer \ HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Microsoft SQL Server \ MSSQL14E.LOCALDB \ MSSQLServer

I tak, zamknąłem i ponownie uruchomiłem instancję LocalDB w obu próbach.

Jednak nie jestem przekonany, że niemożność zmiany domyślnych ścieżek jest błędem, ponieważ może to być po prostu słaba dokumentacja i słaba obsługa błędów w połączeniu. Mówię to, ponieważ właśnie próbowałem edytować domyślne lokalizacje dla SQL Server LocalDB w wersjach 2014, 2016 i 2017, a wszystkie spowodowały dokładnie ten sam błąd, który sam w sobie jest dziwny z powodu bycia z RegCreateKeyEx(), który powinien zajmować się rejestrem i nie system plików.

Brak możliwości zmiany ścieżki jest niefortunny z powodu braku odwrotnego ukośnika podczas tworzenia nowej bazy danych bez określania plików do użycia. Udało mi się jednak utworzyć nową bazę danych przy użyciu pełnej CREATE DATABASEskładni w następujący sposób:

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
Solomon Rutzky
źródło
Przyjmujemy podejście w konfiguracji bazy danych, że jeśli jest to połączenie LocalDb, określamy ścieżkę do pliku MDF, tak jak w obejściu. Nie wydaje się jednak konieczne podawanie nazwy LDF lub LOG ONsekcji CREATE DATABASEinstrukcji. Pliki LDF wydają się być tworzone domyślnie w tej samej lokalizacji, co plik MDF. (Nasz przypadek użycia LocalDb dotyczy głównie testów automatycznych.)
tgharold
@tgharold Proszę zobaczyć aktualizację u góry mojej odpowiedzi. Ten błąd został bardzo niedawno naprawiony w nowej łatce CU6 :-).
Solomon Rutzky
5

Natknąłem się na ten sam problem i znalazłem obejście, które nie powinno mieć żadnych wyraźnych wad (jeśli coś zapomnę, popraw mnie) . Opiera się na odpowiedzi Solomons, ale bez potrzeby bezpośredniego określania bezwzględnej ścieżki do plików bazy danych.

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)

Używa dynamicznego sql i nie jest całkiem ładna, ale wykonuje zadanie do czasu oficjalnego rozwiązania problemu.

Nikolaj Dam Larsen
źródło
1
Ciekawy. To może być nieco lepiej, aby przesunąć 2nd QUOTENAMEdo 2 z param FORMATMESSAGEi umieścić w cudzysłowie ścieżkę pliku: FORMATMESSAGE(N'CREATE DATABASE %s ON PRIMARY ( NAME = %s, FILENAME = "%s" )', QUOTENAME(@databaseName), QUOTENAME(@databaseName), @dataFilePath);. Ale wydaje się, że działa tak, jak teraz, więc +1 za to podejście. Nadal istnieje możliwość zakodowania nazwy lub przekazania ścieżki: gdy nie chcesz używać USERPROFILEroota. Ale możesz pozwolić na to tutaj i po prostu domyślnie na InstanceDefaultDataPathif @Path IS NULL. :-)
Solomon Rutzky
Dziękuję Ci. Zredagowałem odpowiedź z twoją sugestią. Zgadzam się na stałe, że ścieżka bezwzględna jest zdecydowanie poprawnym rozwiązaniem. W naszym scenariuszu odtwarzamy bazę danych tylko podczas automatycznego testowania i musiałem się upewnić, że będzie ona działać dla wszystkich moich kolegów i zbudować serwer, bez konieczności koordynowania wszystkich osób tworzących folder dokładnie w tej samej ścieżce na komputerze lokalnym. :-)
Nikolaj Dam Larsen
4

Ja też mam do czynienia z tym problemem. Jedynym obejściem, jakie znalazłem, byłoby przyznanie dostępu do zapisu c:\Users\wszystkim (lub coś w tym rodzaju) i umożliwienie mu tworzenia plików mdf, gdziekolwiek zechce.

abatishchev
źródło
1
Dzięki, rozwiązało to również dla mnie! To obejście jest do bani, ale dotyczy tylko naszego lokalnego serwera kompilacji, więc nie dbam o dodatkowe prawa użytkownika.
Hannes Sachsenhofer
@ HannesSachsenhofer: Zgadzam się, to do bani. Ale zespół deweloperów LocalDB obiecał mi, że naprawią ten błąd w nadchodzącym wydaniu poprawki.
abatishchev
Przyznaj wszystkim dostęp do zapisu wydaje mi się dość złym obejściem
Raphael
@Raphael: Dlaczego? Masz wielu użytkowników na swoim urządzeniu deweloperskim? A komu nie ufasz?
abatishchev
2

Dziękujemy za zwięzłe wyjaśnienie tego problemu. Wczoraj spotkałem się z tym samym problemem. Nadal nie znalazłem trwałego rozwiązania, ale oto moje obecne obejście.

Korzystam z funkcji Database.EnsureCreated (), aby utworzyć bazę danych.

Ustaw parametry połączenia, aby uwzględnić ustawienie „ AttachDBFilename = ”.

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

Uruchom aplikację. Wygeneruje błąd:

Nie można dołączyć pliku „. \ ExploreCalifornia.mdf” jako bazy danych „ExploreCalifornia”.

ale utworzy bazę danych.

Następnie zmień parametry połączenia i usuń „ AttachDBFilename = ”.

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

Uruchomiłem aplikację ponownie bez błędów i tabele zostały utworzone.

Doug Abrahamson
źródło
Kilka pytań: po pierwsze, aby się upewnić - początkowo pojawiał się błąd (odmowa dostępu), i to rozwiązało, prawda? Po drugie - SQL Server Management Studio jest jedyną aplikacją wymienioną przez adres IP, i to nie brzmi jak coś, co zrobiłeś stamtąd - z jakiej aplikacji to wszystko zrobiłeś?
RDFozz
Dziękuję za odpowiedź, ale tak naprawdę to nie rozwiązuje mojego problemu. Mój kod testowy tworzy nową bazę danych z prostym CREATE DATABASE [databasename]względem LocalDB, a to samo stwierdzenie powoduje problemy, ponieważ LocalDB błędnie łączy domyślny katalog lokalizacji z losowo generowaną nazwą bazy danych (patrz paragraf 3 i 4 mojego pytania). Potrzebuję sposobu, aby naprawić domyślne lokalizacje, aby ten problem konkatenacji nie wystąpił.
feO2x
Obecnie w ogóle nie jestem w stanie utworzyć bazy danych za pomocą SQL / DDL. Nie ma znaczenia, czy uruchomię instrukcję za pośrednictwem SSMS, kodu, czy gdziekolwiek indziej, ponieważ LocalDB zawsze próbuje utworzyć bazę danych bezpośrednio w katalogu Users (co jest całkowicie błędne, żadne pliki nie mogą istnieć w tym katalogu) .
feO2x
1
Prawdopodobnie źle napisałeś AttachDBFilename.
tgharold