最近,我使用SQL Server Express安装程序和此指令将LocalDB从版本13升级到了版本14。安装后,我停止了版本13的现有默认实例(MSSQLLOCALDB)并创建了一个新实例,该实例自动使用v14.0.1000服务器引擎。

我经常使用LocalDB进行数据库集成测试,即在我的xunit测试中,我创建了一个(临时)数据库,该数据库将在测试完成时删除。从新版本开始,很遗憾,由于以下错误消息,我的所有测试均失败:

CREATE FILE在尝试打开或创建物理文件'C时遇到操作系统错误5(访问被拒绝。): \ Users \ kepflDBd0811493e18b46febf980ffb8029482a.mdf'

奇怪的是mdf文件的目标路径不正确,C:\ Users \ kepfl与DBd0811493e18b46febf980ffb8029482 the.mdf(is is单个测试的数据库名称)。通过简单的命令CREATE DATABASE [databaseName]创建数据库-这里没有什么特别的。

在SSMS中,我看到数据,日志和备份的目标位置如下:



但是,当我尝试更新位置时,又收到另一条错误消息:



如何更新默认位置,以便LocalDB能够再次创建数据库?很明显,LocalDB没有正确组合默认位置目录和数据库文件名-是否有我可以编辑的注册表项?还是有其他内容?

在道格的回答和坟墓的评论后更新

根据此Stackoverflow问题,默认位置也应通过注册表进行更改。但是,如果我尝试找到相应的键“ DefaultData”,“ DefaultLog”和“ BackupDirectory”,则无法在注册表中找到它们。 SQL Server v14是否重命名了这些注册表项,还是将这些信息移出了注册表?

评论

仅供参考,在管理员模式下运行SSMS时,我也无法更新数据库的默认位置。

请在我的答案中查看更新。此错误已在CU6中修复,已于4月中旬发布。.

#1 楼

UPDATE

自SQL Server 2017 CU 6起,此错误已修复。现在可以成功执行以下操作:

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


以下知识库文章中记录了该问题以及在CU6中已修复的事实:FIX:尝试在SQL Server 2017 Express LocalDB中创建数据库时出现“拒绝访问”错误

要获取累积更新,请转到以下页面并获取顶部(即最新)的版本可能比CU6更新,具体取决于您何时看到以下内容:

SQL Server 2017构建版本


SQL Server 2017 CU6之前的信息已过时(2018年发布04-17)

组合的路径名和文件名中缺少反斜杠似乎是SQL Server 2017的一个错误。我自己碰到了它。我什至尝试编辑注册表以在以下两个项中为C:\ Users \ MyAccountName \添加一个DefaultData字符串值(这3个默认路径不在我浏览过的任何LocalDB注册表项中):


计算机\ HKEY_CURRENT_USER \ Software \ Microsoft \ Microsoft SQL Server \ UserInstances \ {some-GUID-value}
计算机\ 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文件的路径,就像您的解决方法一样。但是似乎也不必指定CREATE DATABASE语句的LDF或LOG ON部分的名称。默认情况下,似乎在与MDF文件相同的位置创建了LDF文件。 (我们的LocalDb用例主要用于自动化测试。)

– tgharold
17年12月28日在20:28

@tgharold请在我的答案顶部查看更新。这个错误是最近在新的CU6补丁中修复的:-)。

–所罗门·鲁兹基
18年5月8日在15:23

#2 楼

我遇到了同样的问题,发现了一种应该没有明显缺点的变通办法(如果我忘记了什么,请纠正我)。它基于Solomons的答案,但无需直接指定数据库文件的绝对路径。

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,虽然不完全美观,但是可以完成工作,直到对该问题进行正式修复为止。

评论


有趣。将第二个QUOTENAME移至FORMATMESSAGE的第二个参数并在文件路径周围加上双引号可能会稍好一些:FORMATMESSAGE(N'CREATE DATABASE%s ON PRIMARY(NAME =%s,FILENAME =“%s”)', QUOTENAME(@databaseName),QUOTENAME(@databaseName),@ dataFilePath);。但这似乎可以像您现在所拥有的那样工作,因此请为该方法+1。仍然存在对名称进行硬编码或传递路径的情况:当您不想使用USERPROFILE根目录时。但是您可以在这里允许它,并且如果@Path为NULL,则默认为InstanceDefaultDataPath。 :-)

–所罗门·鲁兹基
18 Mar 7 '18 at 22:33

谢谢。我已经根据您的建议编辑了答案。我同意硬编码绝对路径绝对仍然是有效的解决方案。但是在我们的方案中,我们仅在自动测试期间重新创建数据库,而我必须确保该数据库适用于所有同事和构建服务器,而不必协调每个人在其本地计算机上的完全相同的路径上创建文件夹。 :-)

– Nikolaj Dam Larsen
18年8月8日在5:56

#3 楼

我也面临这个问题。我发现的唯一解决方法是将c:\Users\的写访问权授予所有人(或类似的东西),并让它在任何需要的地方创建mdf文件。

评论


谢谢,这也为我解决了!这种解决方法很糟糕,但是它仅在我们的本地构建服务器上,因此我不在乎其他用户权限。

–汉斯·萨克森霍夫(Hannes Sachsenhofer)
18年3月21日在15:15

@HannesSachsenhofer:我同意,这很糟糕。但是LocalDB开发团队向我保证,他们将在即将发布的修补程序版本中修复此错误。

– abatishchev
18-3-21在19:52



授予所有人访问权限的权限对我来说似乎是一个非常糟糕的解决方法

–拉斐尔
18年5月8日在15:17

@Raphael:为什么?您的开发箱中有多个用户?而你不信任谁?

– abatishchev
18年5月8日在21:08

#4 楼

感谢您对此问题的简要说明。我昨天也遇到了同样的问题。我仍然没有找到永久的解决方案,但这是我当前的解决方法。

我正在使用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
17年11月21日在21:30

感谢您的回答,但这并不能真正解决我的问题。我的测试代码使用针对LocalDB的简单CREATE DATABASE [databasename]创建了一个新数据库,由于LocalDB错误地将默认位置目录与随机生成的数据库名称连接在一起(参见我的问题的第3和第4段),因此该语句引起了问题。我需要一种方法来修复默认位置,以便不会发生此串联问题。

– feO2x
17年11月22日在8:35

目前,我根本无法通过SQL / DDL创建数据库。不管是通过SSMS还是从代码或其他任何位置运行该语句都没有关系,因为LocalDB总是尝试直接在Users目录中直接创建数据库(这是完全错误的,该目录中不允许存在文件) 。

– feO2x
17年11月22日在8:52

您可能拼错了AttachDBFilename。

– tgharold
17年12月27日在18:19