LocalDB v14, mdf dosyaları için yanlış yol oluşturur


34

Son zamanlarda, LocalDB'yi SQL Server Express yükleyicisini ve bu talimatı kullanarak 13'den 14'e yükselttim . Yüklemeden sonra, sürüm 13'ün mevcut varsayılan örneğini (MSSQLLOCALDB) durdurdum ve v14.0.1000 sunucu motorunu otomatik olarak kullanan yeni bir tane oluşturdum.

LocalDB'yi Veri Tabanı Entegrasyonu testleri için kullanıyorum, yani xunit testlerimde test bittiğinde silinen (geçici) bir veri tabanı oluşturuyorum. Yeni sürümden beri, maalesef tüm testlerim aşağıdaki hata mesajı nedeniyle başarısız oluyor:

CREATE FILE, 'C: \ Users \ kepflDBd0811493e18b46febf980ffb8029482a.mdf' dosyasını açmaya veya oluşturmaya çalışırken işletim sistemi hatası 5’le (Erişim reddedildi.) Karşılaştı.

Tuhaf olan şey, mdf dosyasının hedef yolunun yanlış olması, C: \ Users \ kepfl ve DBd0811493e18b46febf980ffb8029482a.mdf ( ters tek bir test için rastgele veritabanı adı) arasında ters eğik çizgi olmamasıdır . Veritabanları basit komutla oluşturulur CREATE DATABASE [databaseName]- burada özel bir şey yok.

SSMS'de veri, günlük ve yedekleme için hedef konumların aşağıdaki olduğunu görüyorum:

LocalDB hedef konumları

Ancak, konumu güncellemeye çalıştığımda başka bir hata mesajı alıyorum:

Güncellemeye çalışırken hata mesajı

LocalDB'nin tekrar veritabanı oluşturabilmesi için varsayılan konumları nasıl güncelleyebilirim? LocalDB'nin varsayılan konum dizinini ve veritabanı dosya adını doğru şekilde birleştirmediği açıktır - düzenleyebileceğim bir kayıt defteri girişi var mı? Veya başka bir şey?

Doug'ın cevabı ve sepupic'in yorumundan sonra güncelleme

Bu Stackoverflow sorusuna göre , varsayılan konumun kayıt defteri aracılığıyla da değiştirilebilir olması gerekir. Ancak ilgili anahtarları "DefaultData", "DefaultLog" ve "BackupDirectory" tuşlarını bulmaya çalışırsam, kayıt defterimde bulamıyorum. SQL Server v14 bu kayıt defteri anahtarlarını yeniden adlandırdı mı veya bu bilgileri kayıt defterinden çıkardı mı?


Bilginize, SSMS'yi yönetici modunda çalıştırırken Veritabanı varsayılan konumlarını da güncelleyemiyorum.
feO2x

1
Lütfen cevabımdaki güncellemeyi görün. Bu hata Nisan ortasından itibaren piyasaya sürülen 6
PB'den

Yanıtlar:


21

GÜNCELLEŞTİRME

SQL Server 2017 için 6 PB'den itibaren bu hata giderildi. Artık aşağıdakileri başarıyla yürütmek mümkün:

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

Sorun ve CU6'da düzeltildiği gerçeği, aşağıdaki KB makalesinde belgelenmiştir:
Düzeltme: SQL Server 2017 Express LocalDB'de bir veritabanı oluşturmaya çalıştığınızda "Erişim engellendi" hatası

Toplu Güncelleme'yi almak için, lütfen aşağıdaki sayfaya gidin ve bunu ne zaman gördüğünüze bağlı olarak CU6'dan daha yeni olabilecek en üst (yani en yeni) yapıyı alın:

SQL Server 2017 yapı sürümleri


AŞAĞIDAKİ BİLGİLER OBSOLETE'DEN SQL SERVER 2017 CU6 (Yayınlanan 2018-04-17)

Kombine Yol + Dosya adında ters eğik çizginin olmaması, SQL Server 2017'de bir hata gibi görünüyor. Sadece kendime rastladım. Aşağıdaki Anahtarların her ikisinde de C: \ Users \ MyAccountName \DefaultData için bir Dize Değeri eklemek üzere Kayıt Defteri'ni düzenlemeyi bile denedim (3 varsayılan yol, baktığım hiçbir LocalDB kayıt defteri anahtarında değil):

  • Bilgisayar \ HKEY_CURRENT_USER \ Yazılım \ Microsoft \ Microsoft SQL Server \ UserInstances \ {some-GUID-value}
  • Bilgisayar \ HKEY_LOCAL_MACHINE \ YAZILIM \ Microsoft \ Microsoft SQL Server \ MSSQL14E.LOCALDB \ MSSQLServer

Ve evet, her iki denemede de kapattım ve LocalDB örneğini tekrar başlattım.

Ancak, varsayılan yolları değiştirememenin bir hata olduğu konusunda ikna olmadım, çünkü sadece kötü dokümantasyon ve hatalı hata yönetimi bir arada olabilir. Bunu söylüyorum, çünkü sadece SQL Server LocalDB sürümleri 2014, 2016 ve 2017 için varsayılan konumları düzenlemeyi denedim ve bunların hepsi RegCreateKeyEx()Kayıt Defteri ile ilgili olması gereken ve kendisinden dolayı tuhaf olan aynı hatayla sonuçlandı. dosya sistemi değil.

Yolu değiştirememek, kullanılacak dosyaları belirtmeden yeni bir Veritabanı oluştururken ters eğik çizgi olmamasından dolayı talihsiz bir durumdur. Ancak, tam CREATE DATABASEsözdizimini aşağıdaki gibi kullanarak yeni bir veritabanı oluşturabildim :

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

Veritabanı kurulumumuzda, eğer bir LocalDb bağlantısı varsa, aynı geçici çözümünüzde olduğu gibi MDF dosyasının yolunu belirlediğimiz yaklaşımı benimsiyoruz. Ancak LDF'nin adını veya ifadenin LOG ONbölümünü belirtmek gerekli görünmüyor CREATE DATABASE. LDF dosyaları, varsayılan olarak, MDF dosyasıyla aynı konumda oluşturulmuş gibi görünmektedir. (LocalDb kullanım durumumuz esas olarak otomatik testlerde kullanılmak içindir.)
28'de tgharold

@tgharold Lütfen cevabımın üstündeki güncellemeyi görün. Bu hata çok yakın bir zamanda yeni CU6 yamasında :-) düzeltildi.
Solomon Rutzky

5

Aynı sorunla karşılaştım ve net bir dezavantajı olmayan bir çözüm buldum (bir şeyi unutursam, lütfen beni düzeltin) . Solomons cevabını temel alır, ancak doğrudan veritabanı dosyalarına mutlak yolu belirtmek zorunda kalmadan.

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)

Dinamik sql kullanır ve tam olarak hoş değildir, ancak konuyla ilgili resmi bir çözüm bulana kadar iş yapılır.


1
İlginç. Bu olabilir 2nd taşımak için biraz daha iyi olması QUOTENAME2. param FORMATMESSAGEve dosya yolu çift tırnak koyun: FORMATMESSAGE(N'CREATE DATABASE %s ON PRIMARY ( NAME = %s, FILENAME = "%s" )', QUOTENAME(@databaseName), QUOTENAME(@databaseName), @dataFilePath);. Ama şimdi olduğu gibi çalışıyor gibi görünüyor, bu yüzden bu yaklaşım için +1. USERPROFILEKök kullanmak istemediğinizde, adı zor kodlayan ya da yoldan geçen bir durum var: Ama bunun için burada izin verebilir ve InstanceDefaultDataPatheğer varsayılan olarak sadece varsayılan @Path IS NULL. :-)
Solomon Rutzky

Teşekkür ederim. Cevabını önerinle değiştirdim. Mutlak yolun kesinlikle geçerli bir çözüm olduğuna karar vermemde hemfikiriz. Ancak senaryomuzda, veritabanını yalnızca otomatik test sırasında yeniden yaratıyoruz ve herkesin yerel makinelerinde aynı yolda bir klasör oluşturmasını koordine etmek zorunda kalmadan tüm meslektaşlarım için çalışacağından ve sunucu oluşturduğundan emin olmam gerekiyordu. :-)
Nikolaj Barajı Larsen

4

Ben de bu sorunla karşı karşıyayım. Bulduğum tek geçici çözüm c:\Users\, Herkese (veya bunun gibi bir şeye) yazma yetkisi vermek ve istediği yerde mdf dosyalarını oluşturmasına izin vermek olacaktır.


1
Teşekkürler, bu benim için de çözüldü! Bu geçici çözüm berbat, ancak yalnızca yerel derleme sunucumuzda var, bu yüzden ek kullanıcı haklarını umursamıyorum.
Hannes Sachsenhofer

@HannesSachsenhofer: Kabul ediyorum, berbat. Ancak LocalDB dev ekibi tarafından vaat edildi, bu hatayı yaklaşan hot-fix sürümünde düzeltecekler.
abatishchev

Hibe yazma erişimi, bana oldukça kötü bir geçici çözüm gibi görünüyor
Raphael,

@Raphael: Neden? Kutuda birden fazla kullanıcı var mı? Ve kime güvenmiyorsun?
abatishchev

2

Bu sorunun özlü açıklaması için teşekkür ederiz. Dün de aynı konuya girdim. Hala kalıcı bir çözüm bulamadım, ancak şu andaki geçici çözümüm.

Veritabanını oluşturmak için Database.EnsureCreated () işlevini kullanıyorum.

Bağlantı dizesini ' AttachDBFilename = ' ayarına dahil edecek şekilde ayarlayın .

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

Uygulamayı çalıştırın. Bir hata üretecektir:

'. \ ExploreCalifornia.mdf' dosyası 'ExploreCalifornia' veritabanı olarak eklenemiyor.

ancak veritabanını yaratacaktır.

Bundan sonra, bağlantı dizesini değiştirin ve ' AttachDBFilename = ' öğesini kaldırın .

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

Hiçbir hata yapmadan uygulamayı tekrar çalıştırdım ve tablolar oluşturuldu.


Birkaç soru: İlk önce, sadece emin olmak için - başlangıçta (Erişim reddedildi) hatası alıyorsunuz ve bu çözüldü, doğru mu? İkincisi - SQL Server Management Studio, IP tarafından belirtilen tek uygulama ve bu oradan yaptığınız bir şeye benzemiyor - tüm bunları hangi uygulamadan yaptınız?
RDFozz

Cevabınız için teşekkürler, ama bu gerçekten sorunumu çözmüyor. Test kodum, CREATE DATABASE [databasename]LocalDB'ye karşı basit olan yeni bir veritabanı oluşturur ve bu çok ifade, LocalDB'nin varsayılan konum dizinini rasgele oluşturulmuş veritabanı adıyla yanlış bir şekilde birleştirmesiyle ilgili sorunlara neden olmaktadır (sorumun 3. ve 4. paragraflarına bakın). Bu birleştirme sorununun oluşmaması için varsayılan konumları düzeltmek için bir yola ihtiyacım var.
feO2x

Şu anda, SQL / DDL üzerinden hiçbir veritabanı oluşturamıyorum. LocalDB her zaman veritabanını doğrudan Kullanıcılar dizininde oluşturmaya çalıştığım için (SSD ile veya koddan veya başka bir yerden) çalıştırmamın bir önemi yok (bu tamamen yanlış, bu dizinde dosya bulunmasına izin verilmez) .
feO2x

1
Muhtemelen yanlış yazmışsınızdır AttachDBFilename.
tgharold
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.