2016-11-16 42 views
0

我想遍歷數據庫連接字符串的集合並針對所有數據庫執行查詢,然後將每個IEnumberable結果合併到一個IEnumerable List中。同步版本是這樣的:異步運行可變數量的LINQ查詢

public ActionResult ListSites() 
{ 
    ConnectionStringSettingsCollection ConnectionStrings = ConfigurationManager.ConnectionStrings; 

    List<SiteInfoModel> lstSites = new List<SiteInfoModel>(); 

    foreach (ConnectionStringSettings cn in ConnectionStrings) 
    { 
     lstSites.AddRange(getSitesForInstance(cn)); 
    } 

    return View("~/Views/Sites/List.cshtml", lstSites); 
} 

private List<SiteInfoModel> getSitesForInstance(ConnectionStringSettings css) 
{    
    using (STContext db = new STContext(css.ConnectionString)) 
    { 
     IEnumerable<SiteTracker.Data.site_info> sites = db.Sites; 

     return (from s in sites 
        orderby s.name 
        select new SiteInfoModel 
        { 
         instance = css.Name, 
         siteName = formatValue(s.name, s.active), 
         siteUrl = formatValue(s.url, s.active), 
         siteId = s.site_id, 
         isActive = s.active 
        }).ToList();     
    } 
} 

這個問題可能有幾個小問題,因爲它感覺就像我有一些不同的東西掙扎:(1)應如何getSitesForInstance()寫?它應該是

private async Task<List<SiteInfoModel>> getSitesForInstance() 

如果它應該是異步的,那麼我該如何編寫linq表達式。我試着將IEnumerable更改爲IQueryable並使用.ToListAsync(),但我得到了關於投影非匿名類型的錯誤。它可以在沒有異步任務的情況下編寫,並且仍然可以跨所有連接字符串同時執行查詢嗎?如果可以以任何方式完成,則是更好或更糟的一種方式。 (2)ListSites()在編寫併發數據庫調用時應該如何查看?我已經看過this example,但它並沒有讓我得到一個可行的解決方案。我玩過這樣的事情:

Task<List<SiteInfoModel>>[] tasks = new Task<List<SiteInfoModel>>[ConnectionStrings.Count]; 

for (int i = 0; i < ConnectionStrings.Count - 1; i++) 
{ 
    tasks[i] = getSitesForInstance(ConnectionStrings[i]); 
} 
Task.WaitAll(tasks); 

...但無法得到那個工作。每個DB調用都會返回一個List。當來自所有任務的結果被組合到變量lstSites中 - 這是視圖模型 - 然後問題/問題被解決/回答。

+0

不知道爲什麼人們投票結束 - 但我也不知道爲什麼它不起作用。什麼不適用於你的異步版本?我在可以正常工作的應用程序中做類似的事情。 –

回答

0

這裏是做這項工作的代碼:

public async Task<ActionResult> ListAsync() 
{    
    ConnectionStringSettingsCollection ConnectionStrings = ConfigurationManager.ConnectionStrings; 

    List<SiteInfoModel> lstSites = new List<SiteInfoModel>(); 

    Task<List<SiteInfoModel>>[] tasks = new Task<List<SiteInfoModel>>[ConnectionStrings.Count]; 

    for (int i = 0; i < ConnectionStrings.Count; i++) 
    { 
     tasks[i] = getSitesForInstanceAsync(ConnectionStrings[i]); 
    } 

    try 
    { 
     Task.WaitAll(tasks.ToArray()); 
    } 
    catch (AggregateException) { } 

    for (int ctr = 0; ctr < tasks.Length; ctr++) 
    { 
     if (tasks[ctr].Status == TaskStatus.Faulted) 
      Console.WriteLine("error occurred in {0}", ConnectionStrings[ctr].Name); 
     else 
     { 
      lstSites.AddRange(tasks[ctr].Result); 
     } 

    } 

    return View("~/Views/Sites/List.cshtml", lstSites); 
} 

private Task<List<SiteInfoModel>> getSitesForInstanceAsync(ConnectionStringSettings css) 
{ 
    return Task.Run(() => getSitesForInstance(css)); 
} 

Visual Studio是抱怨ListAsync()不使用的await關鍵字,但它工作正常。這是一個問題嗎?看起來像Task.WaitAll()正在等待