2017-05-08 5 views
1

をとります。これらの1のリターンの例は、次のようなJSONにシリアライズします:JSONシリアライゼーションは、私は2つのviewmodels(製品やパートを)持っている非常に長い時間

[ 
    { 
     "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を試してみて、シリアル化するときレコードは、それがダウンして5分待っても、シリアライズ処理が完了しません。

私は、次のようなJson.Netを使用してみました:

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

化するJsonResult、に次のコードを返却しようとしたときに、私は、私のコントローラのアクションでは、ためJson.NetからJsonConvertを試してみて、使用することを決めました私のようなEFコアを経由して製品を得る

return Json(products); 

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(); 
JSONに私のオブジェクトを変換するには、同じ効率の問題がありました

どうすればいいですか?

+1

[ask]を読んで、どのようにして 'products'を入手するのかを示してください。 – CodeCaster

+1

これは長時間かかるシリアライズプロセスですか?また、メモリ不足を避けるために、サーバー上で何らかの種類のページングを実装したいと思うかもしれません。 –

+0

@CodeCaster – crackedcornjimmy

答えて

1

シリアライゼーションはそれほど重要ではありませんが、LINQクエリを追加したので、SQLエンティティフレームワークが生成する貧弱な問題であることがわかりました。

最初に、熱心なローディングを使用して、製品表と部品表を結合する必要があります。 Includeメソッド呼び出しを追加するだけで、これを行うことができます。

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

これが行われないと、実際にN + 1個のクエリが実行されます。クエリを実行している実際のSQLクエリを見て、DbContextにこのコードを追加するだけの簡単なテクニックを使用する必要があります。 (あなたがEF6を使用している場合にのみ、これを行い、EFコアはあなたのためのクエリーログを行います。)長いです.Where(w => w.IsActive && (w.Parts.Count(c => c.IsActive) > 0))取るクエリをやっている

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

別の条件を。 Entity FrameworkがHAVING句を生成していると思いますが、生成されたSQLを投稿してクエリを最適化すると役立ちます。

最後に、Selectメソッドでのマイクロ最適化は、Partsプロパティフェッチ式を変更することです。

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

これにより、データベースが非アクティブな部分をフェッチして並べ替えることができなくなります。