异步运行可变数量的LINQ查询
本文关键字:LINQ 查询 运行 异步 | 更新日期: 2023-09-27 18:18:11
我想循环通过db连接字符串的集合,并对所有db执行查询,然后将每个IEnumerable
结果合并为一个IEnumerable List<T>
。
同步版本如下:
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();
}
}
这个问题可能有几个子问题,因为感觉我正在努力解决一些不同的问题:
getSitesForInstance()
应该怎么写?应该是private async Task<List<SiteInfoModel>> getSitesForInstance()
如果它应该是异步的,那么我怎么写linq表达式?我尝试将
IEnumerable
更改为IQueryable
并使用.ToListAsync()
,但我得到了一个关于投射非匿名类型的错误。可以在没有async Task<T>
的情况下编写,并且仍然可以跨所有连接字符串并发执行查询吗?如果两种方法都能做到,那是好还是坏呢?ListSites()在编写并发数据库调用时应该如何看待?我看过这个例子,但它并没有让我得到一个有效的解决方案。我试过这样做:
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);
…但没能成功。每个数据库调用返回一个
List<SiteInfoModel>
。当所有任务的结果组合到变量lstSites中(即视图模型)时,问题就解决了。
这里有两个答案
要在一个变量中获得所有结果-您可以简单地使用Parallel。ForEachhttps://stackoverflow.com/a/12610915/444149或https://msdn.microsoft.com/en-us/library/dd460680 (v = vs.110) . aspx
当谈到async..你需要做的第一件事是使你的方法GetSitesForInstance
异步。只需
- 在方法名前添加async关键字
- 使用.ToListAsync()在查询
2日当调用方法时-在它前面添加'await'
下面是使它工作的代码:
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()正在等待