2017-07-13 8 views
1

プロジェクトを遅延読み込みから熱心な読み込みに移行しています。Entity Framework 6多数の子要素と子要素を含む大きなオブジェクトを読み込むことを熱望します

大きなオブジェクトをすべて子供で取得し、シリアル化してフロントエンドのSPAアプリに送信する必要があります。

が、私は大規模なクエリを構築しましたが、それはあまりにも多くのメモリをとる(VSのデータ診断ツールに示すように、メモリ使用量が200メガバイトでジャンプし、オブジェクト自体は〜60キロバイトであるときJSONにシリアライズ)

Include(x => x.Privileges) 
.Include(x => x.Team.Branch) 
.Include(x => x.Equality) 
.Include(x => x.AddressDetails).Include(x => x.ContactDetails) 

.Include(x => x.EmployeeDetails.GeneralUnavailability) 
.Include(x => x.EmployeeDetails.EligibilityDocuments.Select(z => z.Document.Priviliges)) 
.Include(x => x.EmployeeDetails.Position.PositionPayRuleExceptions).Include(x => x.EmployeeDetails.Position.PositionPayRuleExceptions.Select(z => z.PayRule)).Include(x => x.EmployeeDetails.Position.DefaultOffer) 


.Include(x => x.TransportationMode.ProofOfLicence.Priviliges).Include(x => x.TransportationMode.ProofOfInsurance) 

.Include(x => x.UserAcademicQualifications.Select(z => z.AcademicQualification)).Include(x => x.UserAcademicQualifications.Select(z => z.AcademicQualificationScan.Priviliges)) 

.Include(x => x.ProfessionalRegistrations.Select(z => z.Body)).Include(x => x.ProfessionalRegistrations.Select(z => z.ProfessionalRegistrationScan.Priviliges)) 
.Include(x => x.Unavailabilities.Select(z => z.AbsenceType)).Include(x => x.Unavailabilities.Select(z => z.Document.Priviliges)) 
.Where(x=>x.Id=1) 

I ef6でクエリを作成するのは初めてです...私は今までに遅延読み込みを使用していたからです。それを最適化する方法はありますか?

Priviligesは

ドキュメント、ProfessionalRegistrationScan、AcademicQualificationScan、ProofOfInsurance、ProofOfLicenceは、多くの関係Priviligesに多くを持っているファイルのモデルを使用しているPriviligeモデルの一覧です。

はあなたの助け

UPDATE test..andメモリの使用量として.AsNoTrackingを()を使用してみました

はそれに100メガバイト〜でジャンプしてくれてありがとう。 これは〜60kbのオブジェクトのためにまだちょっと高いです...

+0

あなたは.AsNoTracking()を使用しますか?また、「あまりにも多くのメモリがある」とは、オブジェクトが実際に大きすぎてメモリに収まらない、またはクエリの実行が遅すぎることを意味します。そうであれば、多くのインクルードを含むクエリは特にSQLに変換するのに時間がかかることに注意してください。 – DevilSuichiro

+0

クエリには実行に200msかかりますが、これは遅延読み込みよりも10倍高速です。オブジェクトはMB単位のサイズではそれほど大きくありません。このクエリを実行するだけで、200 MBのメモリが必要になります。これはVSのデータ診断ツールに示されています。 .AsNoTracking()はオブジェクトを切り離しますか?私はまた、私は変更を保存する必要がある場所を持っています.... –

+0

うーん、私は以前に 'AsNoTracking' *増加*メモリ使用量を見たことがないと思う...あなたがしようとすると間違いなくいくつかの問題が発生します後でデータを変更して後で保存することは可能ですが、回避することは可能です。 –

答えて

2

だから..エンティティを追跡する唯一の最適化は

app = db.Users.Include(x => x.Privileges) 
    .Include(x => x.Team.Branch) 
    .Include(x => x.Equality) 
    .Include(x => x.AddressDetails) 
    .Include(x => x.ContactDetails).FirstOrDefault(x=>x.Id==3); 

app = db.Users.Include(x => x.ApplicantDetails.ApplicantOffers.Select(z => z.Offer)) 
     .Include(x => x.ApplicantDetails.ApplicantOffers.Select(z => z.OfferDocument)) 
     .Include(x =>x.ApplicantDetails.AppliedPosition.PositionPayRuleExceptions) 
     .Include(x => x.ApplicantDetails.AppliedPosition.DefaultOffer) 
     .Include(x => x.ApplicantDetails.Branch.AddressDetails).FirstOrDefault(x=>x.Id==3); 

です。基本的にすべてを分割してチャンクにします。 Lazyローディングよりもクエリが少ない

更新: 同じことがef.coreで機能します。ちょうどそれを塊に分割してください。

3

まあ、データはデータの種類です。 実際にはのすべてが必要な場合は、それはあなたができる最高のものです。あなたがやったように、熱心な負荷をかけてAsNoTrackingを使うことは、明らかに助けになります。あなたが見ることができ、本当にわずか数より多くのものがあります:それは何かなら

  1. をすることができますあなたが一度にすべてを取得する必要がデータの量を減らすことができSkipTakeを使用して「ページ」、。ページング中はさらに多くの問合せを発行しますが、個々の問合せは軽くなります。少なくとも、常にユーザーからの要求に基づいて行われます。たとえば、結果の最初のページだけが気になる場合は、残りのデータをすべて取得する必要はありません。

  2. Selectを賢明に使用してください。特定の列のみが必要な場合は、他のDTOクラスまたは陽性オブジェクトに列を選択すると、クエリの要求が軽減されます。

  3. ストアドプロシージャを作成します。このようなことでEFによって生成されたクエリを表示する場合は、大量になる可能性があります。 EFはクエリを最適化するのに比較的優れた仕事をしますが、このように多くの結合を行うと、巨大になることはありません。 SQL Serverは、このSQLをすべて解析し、実際にクエリを実行して結果を返す前に実行計画を立てなければなりません。ストアドプロシージャは、この初期の作業すべてを式から外します。

  4. さらに詳細を最適化できず、すべてのデータを一度に必要とする場合は、本当に唯一のオプションはデータベースにリソースを投入することです。 RAM、十分なコア、高速ドライブ(SSDなどが望ましい)などが十分にあることを確認してください。また、Webサーバーとデータベースサーバー間のネットワークができるだけ高速であることを確認してください。理想的には、それらは同じLAN上になければなりません。ファイアウォールなどを横断しなければならない場合、それは物事を劇的に遅くするでしょう。

+0

ありがとうございます。私はストアドプロシージャオプションを探しています –

関連する問題