第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

哪種方法限制內存使用:對于大型 blob,SqlReader.GetBytes

哪種方法限制內存使用:對于大型 blob,SqlReader.GetBytes

C#
瀟瀟雨雨 2023-08-20 14:33:23
我想確定如何限制從本地數(shù)據(jù)庫檢索 blob 并通過塊將其傳輸?shù)降谌?Web 服務的作業(yè)內的內存使用量。使用 SqlDataReader,我似乎有兩個選擇:創(chuàng)建一個方法,該方法使用帶有偏移量的 GetBytes 來檢索返回 byte[] 的 blob 的一部分。然后,該方法的調用者將負責發(fā)出 Web 請求來傳輸該塊。創(chuàng)建一個使用 GetStream 的方法,并向 ReadAsync 發(fā)出多個請求以填充 byte[] 緩沖區(qū),并使用此緩沖區(qū)發(fā)出 Web 請求,直到傳輸文檔。我更喜歡選項 1,因為它限制了該方法的責任,但是如果我使用偏移量調用 GetBytes,它會將整個偏移量加載到內存中還是 sql server 能夠僅返回請求的小塊?如果我使用選項 2,那么該方法將有兩個職責:從數(shù)據(jù)庫加載一個塊并發(fā)出 Web 請求以將文檔存儲在其他地方。// option 1public async Task<Tuple<int, byte[]>> GetDocumentChunk(int documentId, int offset, int maxChunkSize){    var buffer = new byte[maxChunkSize];    string sql = "SELECT Data FROM Document WHERE Id = @Id";    using (SqlConnection connection = new SqlConnection(ConnectionString))    {        await connection.OpenAsync();        using (SqlCommand command = new SqlCommand(sql, connection))        {            command.Parameters.AddWithValue("@Id", documentId);            using (SqlDataReader reader = await command.ExecuteReaderAsync(CommandBehavior.SequentialAccess))            {                if (await reader.ReadAsync())                {                    int bytesRead = (int)reader.GetBytes(0, offset, buffer, 0, maxChunkSize);                    return new Tuple<int, byte[]>(bytesRead, buffer);                }            }        }    }    return new Tuple<int, byte[]>(0, buffer);}//option 2public async Task<CallResult> TransferDocument(int documentId, int maxChunkSize){    var buffer = new byte[maxChunkSize];    string sql = "SELECT Data FROM Document WHERE Id = @Id";    using (SqlConnection connection = new SqlConnection(ConnectionString))    {        await connection.OpenAsync();        using (SqlCommand command = new SqlCommand(sql, connection))        {            command.Parameters.AddWithValue("@Id", documentId);            using (SqlDataReader reader = await command.ExecuteReaderAsync(CommandBehavior.SequentialAccess))            {                using (Stream uploadDataStream = reader.GetStream(0))                {            }        }    }}
查看完整描述

1 回答

?
交互式愛情

TA貢獻1712條經驗 獲得超3個贊

使用選項 1,您將向源發(fā)出許多請求以獲取數(shù)據(jù),并且GetBytes不會在 SQL 服務器上“搜索”流(如果確實如此,我會感到驚訝),這將是一個非常低效的解決方案。

IAsyncEnumerable

使用選項 2,您可以獲得流并按需處理它,因此您將發(fā)出單個數(shù)據(jù)庫請求,并獲得異步 I/O 的所有好處。

使用C# 8?IAsyncEnumerablePreview將完美地解決您的問題,但到目前為止它還處于階段。

復制到異步

如果您可以獲得需要將內容上傳到的流,那么您可以使用CopyToAsync。但我假設每個塊都將在單獨的請求中上傳。如果是這樣,您可以引入一個組件,它會像 a 一樣發(fā)出嘎嘎聲,但當數(shù)據(jù)庫流在其上調用 CopyToAsync()Stream時,它實際上會將內容上傳到網站:

class WebSiteChunkUploader : Stream

{

? ? ?private HttpClient _client = new HttpClient();

? ? ?public override bool CanWrite => true;

? ? ?public override bool CanRead => false;


? ? ?public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) =>


? ? ? ? ?await _client.PostAsync("localhost", new ByteArrayContent(buffer,offset, count));

}

老好 IEnumerable

不幸的是你不能與yield return混合。但是,如果您決定使用阻塞 api 讀取流,例如,那么您可以使用舊的 good 重寫它:IEnumerableasync/awaitReadyield return


public IEnumerable<Tuple<byte[],int>> TransferDocument(int documentId, int maxChunkSize)

{

? ? string sql = "SELECT Data FROM Document WHERE Id = @Id";

? ? var buffer = new byte[maxChunkSize];

? ? using (SqlConnection connection = new SqlConnection(ConnectionString))

? ? {

? ? ? ? connection.Open();

? ? ? ? using (SqlCommand command = new SqlCommand(sql, connection))

? ? ? ? {

? ? ? ? ? ? command.Parameters.AddWithValue("@Id", documentId);

? ? ? ? ? ? using (SqlDataReader reader = command.ExecuteReader(CommandBehavior.SequentialAccess))

? ? ? ? ? ? using (Stream uploadDataStream = reader.GetStream(0))

? ? ? ? ? ? {

? ? ? ? ? ? ? ? while(var bytesRead = uploadDataStream.Read(buffer, 0, maxChunkSize)) > 0)

? ? ? ? ? ? ? ? ? ?yield return Tuple(buffer, bytesRead);

? ? ? ? ? ? }

? ? ? ? }

? ? }

}


...

async Task DoMyTransfer()?

{

? foreach(var buffer in TransferDocument(1, 10000)) {

? ? await moveBytes(buffer)

? }

}

在這種情況下,您不會與 DB 和 fancy 進行異步 IO Tasks,但我想您無論如何都需要限制此上傳操作,以免連接導致數(shù)據(jù)庫過載。


查看完整回答
反對 回復 2023-08-20
  • 1 回答
  • 0 關注
  • 128 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號