从 SQL 服务器数据库读取数据时出错

Error when reading data from SQL Server database

我有一个启用了文件流的数据库

我可以写入数据库,但是当我尝试读回数据时出现此错误

An unhandled exception of type 'System.ComponentModel.Win32Exception' occurred in System.Data.dll Additional information: The user name or password is incorrect

我要执行的代码是这样的

public void ReadFromDatabase()
{
    using (SqlConnection connection = new SqlConnection(sql_ConnectionString))
    {
        connection.Open();
        SqlCommand cmd = new SqlCommand("SELECT TOP(1) Video.PathName(), GET_FILESTREAM_TRANSACTION_CONTEXT() FROM Library", connection);

        SqlTransaction sqlTrans = connection.BeginTransaction(IsolationLevel.ReadCommitted);
        cmd.Transaction = sqlTrans;

        using (SqlDataReader reader = cmd.ExecuteReader()) 
        {
            while (reader.Read())
            {
                string path = reader.GetString(0);
                byte[] transContext = reader.GetSqlBytes(1).Buffer;

                using (Stream fileStream = new SqlFileStream(path, transContext, FileAccess.Read, FileOptions.SequentialScan, allocationSize: 0))
                {
                    byte[] data = new byte[fileStream.Length];
                    fileStream.Read(data, 0, (int)fileStream.Length);

                    File.WriteAllBytes(@"C:\Users\Georgi\AppData\Local\VideoPresenter\temp.mp4", data);
                }
            }
        }
    }
}

我正在使用集成安全性,因此用户和密码未更改并硬编码到应用程序中。

这里是连接字符串代码

//Create a string builder object
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
//Set the properties of the builder
builder.AsynchronousProcessing = false;
builder.DataSource = "xxx.xxx.xxx.xxx";
builder.IntegratedSecurity = true;
builder.InitialCatalog = "VideoLibrary";
//Set the connection string and connection objects' data
sql_ConnectionString = builder.ToString();
//try to connect to the server

然后我只使用字符串打开连接

传递的连接字符串是

"Data Source=xxx.xxx.xxx.xxx;Initial Catalog=VideoLibrary;Integrated Security=True"

这是堆栈跟踪

System.Data.dll!System.Data.SqlTypes.SqlFileStream.OpenSqlFileStream(string path, byte[] transactionContext, System.IO.FileAccess access, System.IO.FileOptions options, long allocationSize)   Unknown
System.Data.dll!System.Data.SqlTypes.SqlFileStream.SqlFileStream(string path, byte[] transactionContext, System.IO.FileAccess access, System.IO.FileOptions options, long allocationSize)   Unknown

SQL FILESTREAM TEST CLIENT.exe!SQL_FILESTREAM_TEST_CLIENT.SQLOperations.ReadFromDatabase() Line 158 C# SQL FILESTREAM TEST CLIENT.exe!SQL_FILESTREAM_TEST_CLIENT.MainWindow.GetButton_Click(object sender, System.Windows.RoutedEventArgs e) Line 47 C# PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs) Unknown PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised) Unknown PresentationCore.dll!System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject sender, System.Windows.RoutedEventArgs args) Unknown PresentationCore.dll!System.Windows.UIElement.RaiseEvent(System.Windows.RoutedEventArgs e) Unknown PresentationFramework.dll!System.Windows.Controls.Primitives.ButtonBase.OnClick() Unknown PresentationFramework.dll!System.Windows.Controls.Button.OnClick() Unknown PresentationFramework.dll!System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(System.Windows.Input.MouseButtonEventArgs e) Unknown PresentationCore.dll!System.Windows.UIElement.OnMouseLeftButtonUpThunk(object sender, System.Windows.Input.MouseButtonEventArgs e) Unknown PresentationCore.dll!System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(System.Delegate genericHandler, object genericTarget) Unknown PresentationCore.dll!System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate handler, object target) Unknown PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs) Unknown PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised) Unknown PresentationCore.dll!System.Windows.UIElement.ReRaiseEventAs(System.Windows.DependencyObject sender, System.Windows.RoutedEventArgs args, System.Windows.RoutedEvent newEvent) Unknown PresentationCore.dll!System.Windows.UIElement.OnMouseUpThunk(object sender, System.Windows.Input.MouseButtonEventArgs e) Unknown PresentationCore.dll!System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(System.Delegate genericHandler, object genericTarget) Unknown PresentationCore.dll!System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate handler, object target) Unknown PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs) Unknown PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised) Unknown PresentationCore.dll!System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject sender, System.Windows.RoutedEventArgs args) Unknown PresentationCore.dll!System.Windows.UIElement.RaiseTrustedEvent(System.Windows.RoutedEventArgs args) Unknown PresentationCore.dll!System.Windows.UIElement.RaiseEvent(System.Windows.RoutedEventArgs args, bool trusted) Unknown PresentationCore.dll!System.Windows.Input.InputManager.ProcessStagingArea() Unknown PresentationCore.dll!System.Windows.Input.InputManager.ProcessInput(System.Windows.Input.InputEventArgs input) Unknown PresentationCore.dll!System.Windows.Input.InputProviderSite.ReportInput(System.Windows.Input.InputReport inputReport) Unknown PresentationCore.dll!System.Windows.Interop.HwndMouseInputProvider.ReportInput(System.IntPtr hwnd, System.Windows.Input.InputMode mode, int timestamp, System.Windows.Input.RawMouseActions actions, int x, int y, int wheel) Unknown PresentationCore.dll!System.Windows.Interop.HwndMouseInputProvider.FilterMessage(System.IntPtr hwnd, MS.Internal.Interop.WindowMessage msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) Unknown PresentationCore.dll!System.Windows.Interop.HwndSource.InputFilterMessage(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) Unknown WindowsBase.dll!MS.Win32.HwndWrapper.WndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) Unknown WindowsBase.dll!MS.Win32.HwndSubclass.DispatcherCallbackOperation(object o) Unknown WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs) Unknown WindowsBase.dll!MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(object source, System.Delegate method, object args, int numArgs, System.Delegate catchHandler) Unknown WindowsBase.dll!System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority priority, System.TimeSpan timeout, System.Delegate method, object args, int numArgs) Unknown WindowsBase.dll!MS.Win32.HwndSubclass.SubclassWndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam) Unknown [Native to Managed Transition]
[Managed to Native Transition]
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame) Unknown WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame frame) Unknown WindowsBase.dll!System.Windows.Threading.Dispatcher.Run() Unknown PresentationFramework.dll!System.Windows.Application.RunDispatcher(object ignore) Unknown PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window window) Unknown PresentationFramework.dll!System.Windows.Application.Run(System.Windows.Window window) Unknown PresentationFramework.dll!System.Windows.Application.Run() Unknown SQL FILESTREAM TEST CLIENT.exe!SQL_FILESTREAM_TEST_CLIENT.App.Main() C# [Native to Managed Transition]
mscorlib.dll!System.AppDomain.ExecuteAssembly(string assemblyFile, System.Security.Policy.Evidence assemblySecurity, string[] args) Unknown Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() Unknown mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state) Unknown mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Unknown mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Unknown mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) Unknown mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() Unknown

当我打开 Management Studio 时,我看到了充满数据的行,但我无法从应用程序中读取它

注意:只有默认的 SQL 服务器用户 'sa'。我也尝试过使用它,但结果是一样的。我使用 Windows 用户而不是 'sa' 用户创建数据库

注意:如果我要在连接字符串中使用 DataSource=(local) 运行代码,它就可以工作。

注意:数据库处于 READ_WRITE 模式

我尝试过的:

我尝试重新创建 table 和整个数据库

我尝试重新安装 SQL Server Express

我尝试向 Windows 添加功能,尤其是 Internet 信息服务 -> 万维网服务 -> 安全 -> Windows Authentication/Basic 身份验证

我尝试操纵我正在使用的用户的权限,但它是一个 dbo,所以应该没有问题。

我尝试在不同的机器上运行相同的代码(使用相同的 Microsoft 帐户)*

我尝试设置 FILESTREAM(NON_TRANSACTED_ACCESS = FULL)

** 我知道 FileStream 仅适用于 Windows 身份验证,而我使用的是 windows 8,因此就帐户而言,一切都是相同的(或至少应该是)** 我错过了什么吗?

您得到的是 Win32Exception,而不是 SqlException,这表明问题是在您打开 FILESTREAM 时出现的。您需要采取许多步骤来确保通过 Win32 API 进行远程 FILESTREAM 访问(这是您尝试做的)。重要的更改是在服务器上为端口 445 启用防火墙(请参阅 Configure a Firewall for FILESTREAM Access) and (most importantly) configure the server to Allow remote clients to have streaming access to FILESTREAM data. SQL configuration filestream access level 必须设置为 2。

如果您仍有问题,我还建议您阅读 Filestream Storage 白皮书。我见过神秘的 FILESTREAM 访问被拒绝错误的案例,最终被诊断为管理员弄乱了文件流共享文件夹存储权限。

我希望您已经了解使用集成安全性只能 访问 FILESTREAM。集成安全性 必须 用于获取句柄 path/context (您的 SELECT 语句)并且 用于使用 Win32 API 访问时的场景(即当您尝试打开 SqlFileStream 对象时)。

尝试使用 reader.GetSqlBytes(1).Value 而不是 reader.GetSqlBytes(1).Buffer。缓冲区大小并不总是与值大小相同。缓冲区可能包含真实数据之后的垃圾。通过使用缓冲区,您可以指定无效的上下文。

If I am to run the code with a DataSource=(local) in the connection string it works.

因为这有效而使用 IP 地址无效,我怀疑 SQL 服务器将您的连接视为远程连接而不是本地连接。

打开SQL 服务器配置管理器。 Select SQL 服务器服务。找到您正在使用的 SQL 服务器实例,右键单击并 select Properties。在 FILESTREAM 选项卡上,select 允许远程客户端访问 FILESTREAM 数据

如果我是正确的,那将解决您的问题。

您可能遇到委派问题。
假设以下机器布局:

  • clientPC - 本机运行你的软件
  • sqlSrv - 你的SQL-服务器
  • fStream - 具有文件流共享的机器

您正在使用集成安全性,因此 clientPC 使用 Kerberos 对 sqlSrv 进行身份验证。然后 sqlSrv 尝试对用户进行身份验证以访问 fStream,但失败了。

可能是 Kerberos 委派方案,您必须满足一些要求才能允许。
运行您的 SQL 服务器进程的服务帐户必须 信任委托 (或约束委托)。可能已允许委派给 CIFS/fStream ServicePrincipalName。

Kerberos 约束委派:http://technet.microsoft.com/en-us/library/jj553400.aspx
关于委派的一些屏幕:http://blogs.msdn.com/b/autz_auth_stuff/archive/2011/05/03/kerberos-delegation.aspx
有关 ServicePrincipalNames 的信息:http://blogs.iis.net/brian-murphy-booth/archive/2007/03/09/the-biggest-mistake-serviceprincipalname-s.aspx

我想这个 Win32Exception 是在 WPF 应用程序堆栈中引发和处理的? 在调试 WPF 应用程序时,您可能会多次遇到这种情况,因为它进行 API 调用并且它可能会失败或处理异常并继续处理。