當生成的查詢只需要1/2秒時,為什麼Entity Framework需要30秒才能加載記錄?

.net c# entity-framework linq-to-entities

下面的executeTime是第一次30秒,下次執行同一組代碼時是25秒。在SQL Profiler中觀看時,我立即看到一個登錄,然後它就在那裡坐了大約30秒。然後,只要運行select語句,應用程序就會完成ToList命令。當我從Management Studio運行生成的查詢時,數據庫查詢只需要大約400毫秒。它返回14行和350列。看起來像將數據庫結果轉換為實體所花費的時間非常小,不值得注意。

那麼在數據庫調用之前的30秒內發生了什麼?

如果實體框架這麼慢,我們就不可能使用它。有什麼我做錯了或者我可以改變什麼來加速這一點嗎?

更新:好吧,如果我使用編譯查詢,第一次需要30秒,第二次需要1/4秒。有什麼辦法可以加快第一次通話的速度嗎?

using (EntitiesContext context = new EntitiesContext()) 
{ 
    Stopwatch sw = new Stopwatch(); 
    sw.Start(); 
    var groupQuery = (from g in context.Groups.Include("DealContract") 
                    .Include("DealContract.Contracts") 
                    .Include("DealContract.Contracts.AdvertiserAccountType1") 
                    .Include("DealContract.Contracts.ContractItemDetails") 
                    .Include("DealContract.Contracts.Brands") 
                    .Include("DealContract.Contracts.Agencies") 
                    .Include("DealContract.Contracts.AdvertiserAccountType2") 
                    .Include("DealContract.Contracts.ContractProductLinks.Products") 
                    .Include("DealContract.Contracts.ContractPersonnelLinks") 
                    .Include("DealContract.Contracts.ContractSpotOrderTypes") 
                    .Include("DealContract.Contracts.Advertisers") 
                where g.GroupKey == 6 
                select g).OfType<Deal>(); 
    sw.Stop(); 
    var queryTime = sw.Elapsed; 
    sw.Reset(); 
    sw.Start(); 
    var groups = groupQuery.ToList(); 
    sw.Stop(); 
    var executeTime = sw.Elapsed; 
} 

一般承認的答案

我有同樣的問題,我的查詢需要40秒。

我發現問題出在.Include("table_name")函數上。我擁有的越多,它就越糟糕。相反,我在查詢後立即將我的代碼更改為Lazy Load所需的所有數據,這將總時間從40秒減少到大約1.5秒。據我所知,這完成了同樣的事情。

所以對於你的代碼,它將是這樣的:

var groupQuery = (from g in context.Groups
            where g.GroupKey == 6 
            select g).OfType<Deal>(); 

var groups = groupQuery.ToList();

foreach (var g in groups)
{
    // Assuming Dealcontract is an Object, not a Collection of Objects
    g.DealContractReference.Load();
    if (g.DealContract != null)
    {
        foreach (var d in g.DealContract)
        {
            // If the Reference is to a collection, you can just to a Straight ".Load"
            //  if it is an object, you call ".Load" on the refence instead like with "g.DealContractReference" above
            d.Contracts.Load();
            foreach (var c in d.Contracts)
            {
                c.AdvertiserAccountType1Reference.Load();
                // etc....
            }
        }
    }
}

順便提一下,如果你要在當前代碼中將這行代碼添加到查詢之上,它會將時間縮短到大約4-5秒(在我的選項中仍然過於MergeOption.NoTracking )從我的理解, MergeOption.NoTracking選項禁用更新和插入數據庫的大量跟踪開銷:

context.groups.MergeOption = MergeOption.NoTracking;

熱門答案

這是因為包括。我的猜測是你渴望將大量對象加載到內存中。構建與db實體對應的c#對象需要花費很多時間。

我的建議是嘗試延遲加載您需要的數據。



許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因