我想循环遍历db连接字符串的集合并对所有DB执行查询,然后将每个IEnumberable结果合并到一个IEnumerable List中。同步版本如下所示:
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()在编写并发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)
这里有2个答案
要获得1个变量的所有结果 - 您可以简单地使用Parallel.ForEach https://stackoverflow.com/a/12610915/444149 或https://msdn.microsoft.com/en-us/library/dd460680(v=vs.110).aspx
谈到异步时..
你需要的第一件事是使你的方法GetSitesForInstance
异步。
要做到这一点
2-ND 在调用方法时 - 在它前面添加'await'。
答案 1 :(得分: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()正在等待