我正在使用c# MVC,并有一个odata驱动的视图来显示来自大表(~ 100万行)的数据。许多数据可以直接从数据库中查询和显示,但是需要重新格式化一列,以包含从另一个数据库中查找的数据。
在数据库中的所有100万行上运行这些查找太慢了,但是在返回给用户的20行上运行这些查找就可以了。我不需要对这些列进行排序或筛选。
在行已经被过滤之后,我如何运行这些查找?
一个可能的模式是:
public class LogController : System.Web.Http.OData.OdataController
{
public IQueryable<LogResult> GetLogs(ODataQueryOptions opts)
{
ODataV2(Request);
var logs = LogRepository.All();
/* Do something here to filter out unwanted results */
// I'll need to convert to a list if I'm going to run a foreach over it
var logsList = logs.ToList()
foreach (var log in logsList)
{
log.CalculatedProperty = ExpensiveFunction(log);
}
return logsList.AsQueryable();
}
}
}
或者也许有一种方法可以在返回给用户之前对GetLogs的输出进行后处理?或者我可以用Log的计算性质?
关键是我想运行ExpensiveFunction() 20次,而不是100万次。
您可以使用一些小技巧来防止转换为列表,反之亦然:
/* Do something here to filter out unwanted results */
return logs.Select(l => {
l.CalculatedProperty = ExpensiveFunction(log);
return l; // or even yield return
});
我不能说这个解决方案是最好的,但在某些情况下它可能会更好一些。
可以应用QueryOption然后更新结果吗?
将返回类型更改为IHttpActionResult
var logsList = ops.ApplyTo(logs, new ODataQuerySettings()).toList();
// reform logsList
return MakeGenericResult(logsList.AsQueryable(), logsList.AsQueryable().GetType());
private IHttpActionResult Ok(object content, Type type)
{
var resultType = typeof(OkNegotiatedContentResult<>).MakeGenericType(type);
return Activator.CreateInstance(resultType, content, this) as IHttpActionResult;
}