我有一个mvc控制器动作,返回json,大约需要2秒,我希望这个速度更快,不到1秒。我正在使用控制器动作,并发现返回json的行很慢,直到那里执行的时间少于100毫秒。 是因为我使用IQueryable接口实际的sql到linq查询到达该行,并且只执行了DB查询并且它执行类似" toList()"的操作。我想知道那里到底发生了什么? 或者Controller.Json函数通常很慢,我可以使用更好的东西吗?
public ActionResult GetItems()
{
IQueryable<Item> Items = default(IQueryable<Item>);
Items = myComponent.getItems(); //returns IQueryable
var result = Items.OrderByDescending(m => m.category).ThenBy(m => m.order);
return Json(result, JsonRequestBehavior.AllowGet);
}
答案 0 :(得分:4)
有可能有两个地方可以调整:
对于IQuerable查询,您可以尝试使用sql profiler或尝试调用ToList(),然后返回它以查看它需要多长时间并可能对其进行优化 (没有更多的查询知识,我无法帮助你。)
但是对于第二部分,您可以尝试使用像Json.Net
这样的库来序列化结果从source代码开始,当您调用Json()时,可以看到Mvc使用JavaScriptSerializer
来执行json序列化。 (你也可以通过查看源代码看看实际发生了什么)
从json.net网站的比较图表来看,JavaScriptSerializer
的表现非常糟糕。
所以你可以尝试使用Json.Net实现自己的JsonActionResult,下面是一些示例代码:
来自:Using JSON.NET to return ActionResult
在您的控制器(或基本控制器)
中protected override JsonResult Json(object data, string contentType, System.Text.Encoding contentEncoding, JsonRequestBehavior behavior)
{
return new JsonNetResult
{
Data = data,
ContentType = contentType,
ContentEncoding = contentEncoding,
JsonRequestBehavior = behavior
};
}
JsonNetResult的定义:
public class JsonNetResult : JsonResult
{
public JsonNetResult()
{
Settings = new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
};
}
public JsonSerializerSettings Settings { get; private set; }
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
throw new ArgumentNullException("context");
if (this.JsonRequestBehavior == JsonRequestBehavior.DenyGet && string.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
throw new InvalidOperationException("JSON GET is not allowed");
HttpResponseBase response = context.HttpContext.Response;
response.ContentType = string.IsNullOrEmpty(this.ContentType) ? "application/json" : this.ContentType;
if (this.ContentEncoding != null)
response.ContentEncoding = this.ContentEncoding;
if (this.Data == null)
return;
var scriptSerializer = JsonSerializer.Create(this.Settings);
using (var sw = new StringWriter())
{
scriptSerializer.Serialize(sw, this.Data);
response.Write(sw.ToString());
}
}
}