Объединение FILESTREAM + API потоковой передачи (SqlFileStream) + Группы доступности (HADR) выдает "Неверное имя целевой учетной записи"

Я развертываю решение SQL Server с FILESTREAM и группами доступности, и после исчерпывающих усилий я не могу устранить эту ошибку:

Неверное имя целевой учетной записи

Приложение использует потоковый API (класс SqlFileStream в C#) в среде HADR, и это, кажется, токсичная комбинация. Так как:

1) Нет ошибок в среде без HADR, использующей T-SQL или потоковый API для доступа к данным FILESTREAM

2) Ошибка не возникает в среде HADR, использующей T-SQL для доступа к данным FILESTREAM

3) Ошибка возникает только в среде HADR, использующей потоковый API для доступа к данным FILESTREAM

Я создал минимальное приложение, чтобы воспроизвести проблему. Он делает ту же попытку записи с использованием потокового API для двух версий одной и той же базы данных с поддержкой FILESTREAM; один не в HADR (этот преуспевает), а другой в среде HADR (этот сбой).

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.IO;
using System.Transactions;

namespace TestFileStream
{
  class Program
  {
    private const string ConnStrNoHadr =
     "Data Source=pvsqledi01;Integrated Security=True;Initial Catalog=FileStreamTestNoHadr";

    private const string ConnStrHadr =
     "Data Source=pvsqledi01;Integrated Security=True;Initial Catalog=FileStreamTestHadr";

    static void Main(string[] args)
    {
      Console.WriteLine($"Running as {Environment.UserDomainName}\\{Environment.UserName}");
      Console.WriteLine("Press a key to start");
      Console.ReadKey();

      try
      {
        Run(ConnStrNoHadr, "NO HADR");
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex.Message);
      }

      try
      {
        Run(ConnStrHadr, "HADR");
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex.Message);
      }

      Console.WriteLine("Done");
      Console.ReadKey();
    }

    private static void Run(string connStr, string caption)
    {
      const string TSql = @"
        INSERT INTO PhotoAlbum(PhotoDescription, Photo)
        OUTPUT inserted.Photo.PathName(), GET_FILESTREAM_TRANSACTION_CONTEXT()
        SELECT @PhotoDescription, 0x
            ";

      Console.WriteLine();
      Console.WriteLine($"*** {caption} ***");
      using (var conn = new SqlConnection(connStr))
      {
        using (var cmd = new SqlCommand(TSql, conn))
        {
          using (var ts = new TransactionScope())
          {
            Console.WriteLine($"Open connection");
            conn.Open();

            cmd.Parameters.AddWithValue("@PhotoDescription", "Desc");

            var serverPathName = default(string);
            var serverTxnContext = default(byte[]);

            Console.WriteLine($"Execute INSERT");
            using (var rdr = cmd.ExecuteReader(CommandBehavior.SingleRow))
            {
              rdr.Read();
              serverPathName = rdr.GetSqlString(0).Value;
              serverTxnContext = rdr.GetSqlBinary(1).Value;
              rdr.Close();
            }
            conn.Close();
            Console.WriteLine($"Path: {serverPathName}");

            Console.WriteLine($"Open local FileStream for read");
            using (var source = new FileStream(@"C:\Users\c1159\Desktop\CapLoad Local\Member\CacheTest\MyBlob.dat", FileMode.Open, FileAccess.Read))
            {
              Console.WriteLine($"Open SqlFileStream for write");
              using (var dest = new SqlFileStream(serverPathName, serverTxnContext, FileAccess.Write))
              {
                Console.WriteLine($"Write BLOB");
                source.CopyTo(dest, 1024 * 1024);
                dest.Close();
              }
              source.Close();
            }
            Console.WriteLine($"BLOB has been saved successfully with SqlFileStream");

            ts.Complete();
          }
        }
      }
    }

  }
}

Вот вывод:

Запуск от имени IEHP\pedimssvc
Нажмите клавишу, чтобы начать

*** НЕТ ХАДР ***
Открытое соединение
Выполнить INSERT
Путь: \\PVSQLEDI01\MSSQLSERVER\v02-A60EC2F8-2B24-11DF-9CC3-AF2E56D89593\FileStreamTestNoHadr\dbo\PhotoAlbum\Photo\EF638D14-A012-E811-80C1-005056B83DAB\ HardVoluTVVH Volume5 VolumeTmeVmeHD5
Откройте локальный FileStream для чтения
Откройте SqlFileStream для записи
Написать BLOB
BLOB был успешно сохранен с SqlFileStream

*** Хадр ***
Открытое соединение
Выполнить INSERT
Путь: \\PVLISEDI01\SQLFILESTREAM\v02-A60EC2F8-2B24-11DF-9CC3-AF2E56D89593\FileStreamTestHadr\dbo\PhotoAlbum\Photo\F0638D14-A012-E811-80C1-005056B83DAB\VolumeHint5
Откройте локальный FileStream для чтения
Откройте SqlFileStream для записи
Неверное имя целевой учетной записи
Готово

Ошибка возникает в строке, которая пытается открыть экземпляр SqlFileStream для записи:

using (var dest = new SqlFileStream(serverPathName, serverTxnContext, FileAccess.Write))

Я уже проверил следующее:

  • Учетная запись пользователя Windows IEHP\pedimssvc является учетной записью службы приложения.
  • Он имеет необходимые разрешения для SqlFileStream, о чем свидетельствует успешный результат в среде без HADR.
  • В качестве проверки работоспособности я также попытался использовать ту же учетную запись службы, под которой работает сам SQL Server, и получил те же результаты; работает в среде без HADR, не работает в HADR.
  • Я видел статью в https://docs.microsoft.com/en-us/sql/database-engine/availability-groups/windows/filestream-and-filetable-with-always-on-availability-groups-sql-server. Как объясняется в статье, имя компьютера (PVSQLEDI01) заменяется именем виртуальной сети (PVLISEDI01) в среде HADR. Вывод показывает, что.PathName() возвращает имя компьютера для базы данных, отличной от HADR, и возвращает VNN для базы данных HADR, чего я и ожидал. Также кажется, что имя общего ресурса изменилось с MSSQLSERVER для базы данных не-HADR на SQLFILESTREAM для базы данных HADR, и я не знаю почему. В отчаянии я попытался заменить имя общего ресурса обратно на MSSQLSERVER для базы данных HADR, но это не имело никакого значения.
  • Напомним, что FILESTREAM работает в среде HADR с использованием T-SQL; например, INSERT... VALUES(0xF4E0239A...). И FILESTREAM работает в среде без HADR, используя потоковый API. Проблема возникает только при объединении потокового API со средой HADR.

Это критически важная система; и нам абсолютно необходимо, чтобы эта база данных была частью среды HADR. Так что любая помощь в решении проблемы очень ценится, спасибо!

0 ответов

Другие вопросы по тегам