2016-11-16 7 views
0

DB接続文字列をループし、すべてのDBに対してクエリを実行し、各IEnumberable結果を1つのIEnumerableリストに結合します。同期バージョンは次のようになります。可変数の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()を使用してみましたが、匿名以外の型の投影に関するエラーが表示されます。非同期タスクなしで書かれ、依然としてすべての接続文字列で同時にクエリを実行できますか?それがどちらの方法でもできる場合は、どちらかが良いか悪いかです。

質問のもう1つの部分は、(2)ListSites()は同時DB呼び出しを行うためにどのように書かれていますか?私は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

1つの変数のすべての結果を得るためにここに

2つの答えがあります - あなたは、単に https://stackoverflow.com/a/12610915/444149 または

https://msdn.microsoft.com/en-us/library/dd460680(v=vs.110).aspx非同期について話..あなたが 1-RSTの事を必要とするParallel.ForEachを使用することができますあなたのメソッドGetSitesForInstanceを非同期にすることです。 はちょうど

  • クエリでメソッド名
  • 使用.ToListAsync()の前に非同期キーワードを追加することを行うために、
  • メソッドを呼び出すときに

2-ND - '待つ' を追加それの前に

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キーワードを使用しませんが、それが正常に動作することを不平を言っている:ここ

0

この作品を作ったコードがあります。これは問題ですか? Task.WaitAll()が待っているようです。

関連する問題