我们要根据传递给该方法的值列表来过滤出“视图”行。
public List<Model.View_RegOrgUserInfo> GetAdminInfoList(List<string> adminWwids)
{
try
{
using (var ctx = new Context())
{
return ctx.View_RegOrgUserInfo.Where(x => adminWwids.Contains(x.WWID.Value.ToString())).ToList();
}
}
catch (Exception ex)
{
onboardingLogger.LogException(ex); throw ex;
}
}
adminWWIDs
是字符串列表,而View中的WWID
列是int?
,但是我们在这里看到了超时异常。 adminWWIDs
列表包含约1万个项目,视图包含约20万行
我不确定我们在做错什么以及如何提高效率。
例外:
"Message":"An error has occurred.","ExceptionMessage":"The wait operation timed out","ExceptionType":"System.ComponentModel.Win32Exception"
答案 0 :(得分:0)
根据对数据库的访问,10,000个列表的更改频率以及调用频率,您可以将10,000个项目加载到数据库的临时表中,然后使用EF连接获取您想要的数据。
当然,您可以遍历200,000行,并使用LINQ作为对象来比较和查找数据,但是除非它是一个很小的表和一个本地数据库,否则可能不会很有效。
答案 1 :(得分:0)
对于操作超时异常,是因为默认情况下EF具有15或30秒的超时时间。
对您的代码进行IP改进:
1-添加以下代码,以便您的查询完成并且不会引发异常
ctx.Database.CommandTimeout = 3000;
2-使用异步始终是最佳实践
3-使用AsNoTracking()
await ctx.View_RegOrgUserInfo.Where(x => adminWwids.Contains(x.WWID.Value.ToString())).AsNoTracking().ToListAsync();
4-您可以尝试在函数内部将列表转换为列表,然后
await ctx.View_RegOrgUserInfo.Where(
x => x.WWID != null &&
adminWwids.Contains(x.WWID)
).AsNoTracking().ToListAsync();
如果上述方法仍然不能满足您的要求,则可以尝试执行以下操作:
var parameters = string.Join("," , adminWwids);
var query = $"SELECT * FROM VIEW_REGORUSERINFO WHERE WWID IN (parameters);
return await db.Database.SqlQuery<VIEW_REGORUSERINFO>(query).AsQueryable().AsNoTracking().ToListAsync();