Создайте API-интерфейс get, который возвращает BLOB. net core (EF) - PullRequest
4 голосов
/ 31 января 2020

У меня есть база данных с таблицей, которая имеет идентификатор и большой двоичный объект. То, что я хочу, - это получить большой двоичный объект и, по сути, передать его клиенту, а не извлекать его из памяти. Это потому, что большой двоичный объект может быть очень большим (100 МБ).

Я почти достиг этого, используя SQLdataReader. Делая это, когда я делаю запрос на получение, он начинает загрузку немедленно, и нет никаких накладных расходов на память. При этом использовался. net core 2.2 Однако, когда я перешел на. net core 3.1, теперь он не работает, и память заполняется сотнями мегабайт. Я также хотел бы добиться того же результата, используя Entity Framework, но до сих пор я не нашел хороших онлайн-ресурсов.

Вот код, который у меня есть до сих пор.

[HttpGet]
    public  IEnumerable<Byte[]> GetStreaming()
    {

        var header = Request.Headers["Accept-Encoding"];
        System.Console.WriteLine(header);

        string connectionString = "Data Source=myPc\\SQLEXPRESS;Initial Catalog=dbo;Persist Security Info=True;User ID=sa;Password=admin";

        //----------------------
        SqlConnection connection = new SqlConnection(connectionString);

        connection.Open();

        SqlCommand command = new SqlCommand("exec getBlob", connection);

        SqlTransaction tran = connection.BeginTransaction(IsolationLevel.ReadCommitted);
        command.Transaction = tran;
        byte[] buffer = new byte[5000000];
        long position = 0;
        long bytesRead = 5000000;
        using (SqlDataReader reader = command.ExecuteReader(CommandBehavior.SequentialAccess))
        {
            reader.Read();
            reader.GetBytes(0, position, null, 0, 5000000);
            while (bytesRead == 5000000)
            {
                // Get the pointer for file
                bytesRead = reader.GetBytes(0, position, buffer, 0, 5000000);
                position += bytesRead;
                yield return buffer;

                // Create the SqlFileStream

            }

        }

    }

Я пытался просто сделать это так

        public  IEnumerable<byte[]> DownloadFile()
    {

        yield return  context.t_noFs.Where(u => u.Id == 1)
            .Select(u => u.dat).
            FirstOrDefault();
    }

, и хотя это возвращает значение , он не имеет желаемого эффекта и заполняет память.

1 Ответ

1 голос
/ 31 января 2020

В вашем случае рекомендуется использовать потоки.

[HttpGet]
public  FileStreamResult GetStreaming()
{
    var header = Request.Headers["Accept-Encoding"];
    System.Console.WriteLine(header);

    string connectionString = "Data Source=myPc\\SQLEXPRESS;Initial Catalog=dbo;Persist Security Info=True;User ID=sa;Password=admin";

    //----------------------
    SqlConnection connection = new SqlConnection(connectionString);

    connection.Open();

    SqlCommand command = new SqlCommand("exec getBlob", connection);

    SqlTransaction tran = connection.BeginTransaction(IsolationLevel.ReadCommitted);
    command.Transaction = tran;
    SqlDataReader reader = command.ExecuteReader(CommandBehavior.SequentialAccess)
    var blobStream = reader.GetStream(0);

    return new FileStreamResult(blobStream, "application/x-binary")
    {
         FileDownloadName = "your file name"
    };
}
...