LocalDB v14 cria caminho incorreto para arquivos mdf

34

Recentemente, atualizei o LocalDB da versão 13 para 14 usando o instalador do SQL Server Express e esta instrução . Após a instalação, parei a instância padrão existente (MSSQLLOCALDB) da versão 13 e criei uma nova, que usava automaticamente o mecanismo do servidor v14.0.1000.

Costumo usar o LocalDB para testes de integração de banco de dados, ou seja, em meus testes xunit, crio um banco de dados (temporário) que é excluído quando o teste termina. Desde a nova versão, infelizmente todos os meus testes falham devido à seguinte mensagem de erro:

CREATE FILE encontrou o erro do sistema operacional 5 (acesso negado.) Ao tentar abrir ou criar o arquivo físico 'C: \ Users \ kepflDBd0811493e18b46febf980ffb8029482a.mdf'

O estranho é que o caminho de destino para o arquivo mdf está incorreto, falta uma barra invertida entre C: \ Users \ kepfl e DBd0811493e18b46febf980ffb8029482a.mdf (que é o nome aleatório do banco de dados para um único teste). Os bancos de dados são criados através do comando simples CREATE DATABASE [databaseName]- nada de especial aqui.

No SSMS, vejo que os locais de destino para dados, log e backup são os seguintes:

Locais de destino do LocalDB

No entanto, quando tento atualizar o local, recebo outra mensagem de erro:

Mensagem de erro ao tentar atualizar

Como posso atualizar os locais padrão para que o LocalDB possa criar bancos de dados novamente? É óbvio que o LocalDB não combina corretamente o diretório de localização padrão e o nome do arquivo de banco de dados - há uma entrada de registro que eu possa editar? Ou qualquer outra coisa?

Atualização após a resposta de Doug e o comentário de sepupic

De acordo com essa pergunta do Stackoverflow , os locais padrão também devem ser alteráveis ​​por meio do registro. No entanto, se eu tentar encontrar as chaves correspondentes "DefaultData", "DefaultLog" e "BackupDirectory", não consigo encontrá-las no meu registro. O SQL Server v14 renomeou essas chaves do registro ou moveu essas informações para fora do registro?

feO2x
fonte
Para sua informação, também não consigo atualizar os locais padrão do Banco de Dados ao executar o SSMS no modo de administrador.
precisa saber é
1
Por favor, veja a atualização na minha resposta. Este bug foi corrigido a partir de CU6, lançado em meados de abril ..
Solomon Rutzky

Respostas:

21

ATUALIZAR

No CU 6 para SQL Server 2017, esse bug foi corrigido. Agora é possível executar o seguinte com êxito:

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

O problema e o fato de ele estar corrigido no CU6 estão documentados no seguinte artigo da Base de Dados de Conhecimento:
CORRECÇÃO: Erro "Acesso negado" ao tentar criar um banco de dados no SQL Server 2017 Express LocalDB

Para obter a atualização cumulativa, vá para a página a seguir e pegue a versão superior (ou seja, mais recente), que pode ser mais recente que o CU6, dependendo de quando você vê isso:

Versões de compilação do SQL Server 2017


INFO ABAIXO OBSOLETO NO SQL SERVER 2017 CU6 (Lançado 2018-04-17)

A falta de uma barra invertida no nome do arquivo Path + File combinado parece ser um bug no SQL Server 2017. Acabei de me deparar com ele. Eu até tentei editar o Registro para adicionar uma DefaultDatastring Valor para C: \ Users \ MyAccountName \ nas duas Chaves a seguir (os 3 caminhos padrão não estão em nenhuma das chaves de registro LocalDB que eu procurei):

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

E sim, desliguei e iniciei novamente a instância LocalDB nas duas tentativas.

No entanto, não estou convencido de que não ser capaz de alterar os caminhos padrão seja um bug, pois pode ser apenas uma documentação ruim e um tratamento de erros ruim combinado. Digo isso porque tentei editar os locais padrão para as versões 2014, 2016 e 2017 do SQL Server LocalDB, e todos resultaram no mesmo erro exato, o que por si só é estranho por ser de RegCreateKeyEx(), que deveria estar lidando com o Registro e não o sistema de arquivos.

Não é possível alterar o caminho é lamentável devido à falta de barra invertida ao criar um novo banco de dados sem especificar os arquivos a serem usados. No entanto, consegui criar um novo banco de dados usando a CREATE DATABASEsintaxe completa da seguinte maneira:

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
fonte
Estamos adotando a abordagem em nossa configuração de banco de dados de que, se for uma conexão LocalDb, especificamos o caminho do arquivo MDF, exatamente como na sua solução alternativa. Mas não parece necessário especificar também o nome do LDF ou LOG ONseção da CREATE DATABASEinstrução. Os arquivos LDF parecem ter sido criados, por padrão, no mesmo local que o arquivo MDF. (Nosso caso de uso de LocalDB é principalmente para uso em testes automatizados.)
tgharold
@tgharold Consulte a atualização na parte superior da minha resposta. Este bug foi corrigido muito recentemente no novo patch CU6 :-).
Solomon Rutzky
5

Corri para o mesmo problema e encontrei uma solução alternativa que não deveria ter nenhuma desvantagem clara (se estou esquecendo algo, corrija-me) . É baseado na resposta de Salomão, mas sem a necessidade de especificar o caminho absoluto para os arquivos do banco de dados diretamente.

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)

Ele usa sql dinâmico e não é exatamente bonito, mas faz o trabalho até que haja uma correção oficial do problema.

Nikolaj Dam Larsen
fonte
1
Interessante. Ele pode ser um pouco melhor para mover a 2 QUOTENAMEpara o 2º param de FORMATMESSAGEe colocar aspas em torno do caminho do arquivo: FORMATMESSAGE(N'CREATE DATABASE %s ON PRIMARY ( NAME = %s, FILENAME = "%s" )', QUOTENAME(@databaseName), QUOTENAME(@databaseName), @dataFilePath);. Mas parece funcionar como você o tem agora, então marque +1 nesta abordagem. Ainda é possível codificar o nome ou passar um caminho: quando você não deseja usar a USERPROFILEraiz. Mas você pode permitir isso aqui e usar como padrão o InstanceDefaultDataPathif @Path IS NULL. :-)
Solomon Rutzky
Obrigado. Editei a resposta com sua sugestão. Concordo que codificar o caminho absoluto ainda é definitivamente uma solução válida. No entanto, em nosso cenário, recriamos o banco de dados apenas durante os testes automáticos e eu tive que garantir que funcionasse para todos os meus colegas e criar servidor, sem precisar coordenar todos os que criam uma pasta exatamente no mesmo caminho em sua máquina local. :-)
Nikolaj Dam Larsen
4

Também estou enfrentando esse problema. A única solução alternativa que encontrei seria conceder acesso de gravação c:\Users\a Todos (ou algo assim) e permitir que ele criasse os arquivos mdf onde quisesse.

abatishchev
fonte
1
Obrigado, isso resolveu para mim também! Essa solução alternativa é péssima, mas é apenas em nosso servidor de compilação local, por isso não me importo com os direitos adicionais do usuário.
Hannes Sachsenhofer
@ HannesSachsenhofer: Eu concordo, é uma merda. Mas a equipe de desenvolvedores do LocalDB me prometeu que eles corrigiriam esse bug na próxima versão do hotfix.
precisa saber é o seguinte
Grant acesso de escrita a todos parece ser uma muito má solução para mim
Raphael
@Raphael: Por quê? Você tem vários usuários em sua caixa de desenvolvimento? E em quem você não confia?
Abatishchev
2

Obrigado pela sua explicação concisa deste problema. Encontrei esse mesmo problema ontem. Ainda não encontrei uma solução permanente, mas aqui está minha solução atual.

Estou usando a função Database.EnsureCreated () para criar o banco de dados.

Defina a cadeia de conexão para incluir a configuração ' AttachDBFilename = '.

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

Execute o aplicativo Isso irá gerar um erro:

Não é possível anexar o arquivo '. \ ExploreCalifornia.mdf' como o banco de dados 'ExploreCalifornia'.

mas criará o banco de dados.

Depois disso, altere a cadeia de conexão e remova ' AttachDBFilename = '.

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

Executei o aplicativo novamente sem erros e as tabelas foram criadas.

Doug Abrahamson
fonte
Algumas perguntas: Primeiro, só para ter certeza - você estava recebendo um erro (Acesso negado) inicialmente, e isso resolveu isso, correto? Segundo - o SQL Server Management Studio é o único aplicativo mencionado pelo IP, e isso não soa como algo que você fez a partir daí - de qual aplicativo você fez tudo isso?
RDFozz
Obrigado pela sua resposta, mas isso realmente não resolve o meu problema. Meu código de teste cria um novo banco de dados com um simples CREATE DATABASE [databasename]contra o LocalDB e essa mesma instrução está causando problemas, pois o LocalDB concatena erroneamente o diretório de locais padrão com o nome do banco de dados gerado aleatoriamente (consulte os parágrafos 3 e 4 da minha pergunta). Preciso de uma maneira de corrigir os locais padrão para que esse problema de concatenação não ocorra.
feO2x
Atualmente, não consigo criar um banco de dados via SQL / DDL. Não importa se eu executo a instrução via SSMS, ou a partir do código ou de qualquer outro lugar, porque o LocalDB sempre tenta criar o banco de dados diretamente no diretório Users (o que é completamente errado, não é possível que exista nenhum arquivo nesse diretório) .
feO2x
1
Você possivelmente digitou incorretamente AttachDBFilename.
tgharold