.net - JSON 序列化需要很长时间

标签 .net json asp.net-web-api serialization json.net

我有两个 ViewModel(产品和零件):

public class ProductViewModel
{
    public int Id { get; set; }

    public string Name { get; set; }

    public string Description { get; set; }       

    public bool IsActive { get; set; }

    public IEnumerable<PartViewModel> Parts { get; set; }
}

public class PartViewModel
{
    public int Id { get; set; }

    public string Name { get; set; }

    public bool IsActive { get; set; }
}

我运行 EF Core 查询,该查询返回 1727 个产品,每个产品至少有 1 个部件。返回其中 1 个的示例将序列化为 JSON,如下所示:

[  
   {  
      "Id":8761,
      "Name":"Product Name 1",
      "Description":"This is a product",
      "IsActive":true,
      "Parts":[  
         {  
            "Id":103767,
            "Name":"Name 1"
            "IsActive":true
         },
         {  
            "Id":156436,
            "Name":"Name 2",
            "IsActive":true
         },
         {  
            "Id":109436,
            "Name":"Name 3",
            "IsActive":true
         }
      ]
   }
]

现在,这对于我 .Take(10) 的查询效果很好,尽管看起来很慢,但当我尝试序列化 1727 条记录时,它陷入困境,五分钟的等待甚至无法完成序列化过程。

我尝试使用 Json.Net:

var ret = JsonConvert.SerializeObject(products, new JsonSerializerSettings { Formatting = Formatting.Indented });

我只是决定尝试使用 Json.Net 中的 JsonConvert,因为在我的 Controller 操作中,当尝试返回 JsonResult 时,以下将我的对象转换为 JSON 的代码也存在相同的效率问题:

return Json(products);

我通过 EF Core 获取产品,如下所示:

var products = _context.Products.OrderBy(o => o.Name).Where(w => w.IsActive  //all products are active
            && (w.Parts.Count(c => c.IsActive) > 0)) //remove parts that are
            .Select(pr => new ProductViewModel
            {
                Id = pr.Id,
                Name = pr.Name,
                Description = pr.Description,
                IsActive = pr.IsActive,
                Parts = pr.Parts.OrderBy(o => o.Name).Where(w => w.IsActive)  //all parts are active
                .Select(prt => new PartViewModel
                {
                    Id = prt.Id,
                    Name = prt.Name,
                    IsActive = prt.IsActive,
                })
            }).ToList();

我能做什么?

最佳答案

序列化并不是什么大问题,现在您已经添加了 LINQ 查询,很容易注意到问题是从中生成的 SQL Entity Framework 很差。

首先,您应该使用预加载将产品表与零件表连接起来。您只需添加 Include 方法调用即可做到这一点。

_context.Products.Include(p => p.Parts)

如果不这样做,查询实际上会执行 N + 1 次查询。您应该使用一个简单的技巧来观察您的查询正在执行的实际 SQL 查询,将此代码添加到您的 DbContext 中。 (仅当您使用 EF6 时才执行此操作,EF Core 会为您执行查询日志记录。)

public YourDBContext()
{
   #if DEBUG   
   this.Database.Log = msg =>
   {
       Debugger.Log(1, "ALL", "EF DB SQL: " + msg + Environment.NewLine);
   };
   #endif
}

另一个导致查询时间较长的条件是 .Where(w => w.IsActive && (w.Parts.Count(c => c.IsActive) > 0))。我猜 Entity Framework 正在生成一个 HAVING 子句,但如果您发布生成的 SQL 来优化查询,它会有所帮助。

最后,Select 方法中的一个微优化是更改 Parts 属性获取表达式。

// other properties ...
Parts = pr.Parts.Where(w => w.IsActive).OrderBy(o => o.Name),
// other properties ...

这将阻止您的数据库获取和排序不活动的部分。

关于.net - JSON 序列化需要很长时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43851097/

相关文章:

php - Android Php Mysqli : Response cannot be parsed as JSON data

c# - Asp.Net Web Api 在 Godaddy 服务器上不工作,但在本地工作正常

C#不继承基类的构造函数

.net - 在运行时向 WPF TreeViewItem 添加图标

c# - 使用 `dynamic` 与 `object` 的性能成本?

jQuery parseJson 对象方向(IE 和 Firefox 与 Opera 和 Chrome)

asp.net-mvc - 使用 JSON、JQuery 将复杂对象数组发布到 ASP.NET MVC Controller

Azure 应用服务部署无法发布 "no files found"

c# - WebAPI 2.1 中的 Ninject 错误 - 确保 Controller 具有无参数公共(public)构造函数

c# - ServiceStack CORS - 仅在 IE 中不响应 OPTIONS 请求