簡體   English   中英

第一次調用后,對不同數據庫上下文的 EF 查詢似乎會緩存

[英]EF queries to different DB contexts seem to cache after the first call

我有一個包含三個表的數據庫,我正在制作一個程序,它將 select 並且需要同時顯示所有三個表的結果。

為了加快記錄的獲取速度,我決定使請求異步,以便它們可以同時發生。
由於您不能在同一個 DB 上下文上執行多個並發操作,因此我總共只實例化三個上下文,並在每個上下文上啟動 Linq 查詢“ToListAsync()”。

但是發生了一些奇怪的事情(對我來說)——異步版本並不比同步版本快。 無論我是使用“.ToListAsync()”異步獲得結果還是使用“.ToList()”同步獲得結果,它們都需要相同的時間。 使用同步版本,第一個操作大約需要 2 秒才能完成,而第二個大約需要 170 毫秒,第三個大約需要 90 毫秒。 我想某種執行計划或緩存或建立連接是什么使第一個請求需要很多時間,而其他請求幾乎立即完成,但我想知道為什么會發生這種情況以及是否有辦法做到這一點快點。
忘了提到異步版本需要相同的時間 - 2s。

相關代碼:

        int maxRecords = 10;
        var resultsTableOne = dbContext.tableOne.Where(log =>
                                            log.DateUtc >= dateFrom || dateFrom == null)
                                        && (log.DateUtc <= dateTo || dateTo == null))
                                            .OrderByDescending(log => log.Id).Take(maxRecords).ToList();
        var resultsTableTwo = dbContext.tableTwo.Where(log =>
                                            log.DateUtc >= dateFrom || dateFrom == null)
                                        && (log.DateUtc <= dateTo || dateTo == null))
                                            .OrderByDescending(log => log.Id).Take(maxRecords).ToList();
        var resultsTableThree = dbContext.tableThree.Where(log =>
                                            log.DateUtc >= dateFrom || dateFrom == null)
                                        && (log.DateUtc <= dateTo || dateTo == null))
                                            .OrderByDescending(log => log.Id).Take(maxRecords).ToList();

此處簡化了 select 條件。 對於異步版本,“ToList”被替換為“ToListAsync”,它返回一個任務,在此處顯示的代碼之后調用“GetAwaiter().GetResult()”(並且“dbContext”被替換為三個單獨的實例)。

附言
同步版本的結果與一個和三個 DbContext 相同。 即,所有三個操作是在同一個實例上執行還是在其自己的實例上執行都需要相同的時間。

為了加快記錄的獲取速度,我決定使請求異步,以便它們可以同時發生。

這不是async / await模式所做的。 您似乎想要做的是並行化,您可以使用async方法及其關聯的Task ,但這需要 3 個不同的 DbContext 實例。 作為與您擁有的代碼相關的一個非常簡單的示例:

using (var context1 = new AppDbContext())
{
    using (var context2 = new AppDbContext())
    {
        using (var context3 = new AppDbContext())
        {
            var table1Task = context1.tableOne
                .Where(log =>
                    log.DateUtc >= dateFrom || dateFrom == null)
                    && (log.DateUtc <= dateTo || dateTo == null))
                .OrderByDescending(log => log.Id)
                .Take(maxRecords).ToListAsync();
            var table2Task = context2.tableTwo
                .Where(log =>
                    log.DateUtc >= dateFrom || dateFrom == null)
                    && (log.DateUtc <= dateTo || dateTo == null))
                .OrderByDescending(log => log.Id)
                .Take(maxRecords).ToListAsync();
            var table3Task = context3.tableThree
                .Where(log =>
                    log.DateUtc >= dateFrom || dateFrom == null)
                    && (log.DateUtc <= dateTo || dateTo == null))
                .OrderByDescending(log => log.Id)
                .Take(maxRecords).ToListAsync();
           var resultTask = Task.WhenAll(table1Task, table2Task, table3Task);
           try
           {
               resultTask.Wait();
               var result1 = table1Task.Result;
               var result2 = table2Task.Result;
               var result3 = table3Task.Result;
               // Use your 3 lists.
           }
           catch(Exception ex)
           {// Handle any exception when running.
           }
        }
    }
}

每個查詢都必須在單獨的 DbContext 上運行,因為 DbContext 不是線程安全的。

正如評論中所提到的,為了提高性能,包括索引和使用投影而不是返回整個實體,還有更好的方法需要研究。 如果 Table1 的行非常大,其中包含許多結果代碼不需要的大字段,則使用Select進行投影以獲取您需要的列可以幫助提供更高性能的代碼。 並行性只是我在面對運行多個查詢時會考慮的事情,其中一個或多個查詢可能需要大量時間,並且每個查詢的結果是完全獨立的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM