2010-09-21 13 views
9

Projemde EntityFramework 4'ü veriyle çalışmak için kullanıyorum. Basit bir sorgu ile korkunç performans sorunları buldum. EF4 tarafından oluşturulan bir sql sorgusunda profilleyiciye baktığımda şok oldum.Varlık Çerçevesi'nde Linq sorguları 4. Korkunç performans

benim varlık veri modeli bazı tablolar vardır: Oldukça basit görünüyor

Data Model

. Tüm ilgili öğeleri, ilgili tüm gezinme özellikleriyle seçmeye çalışıyorum. Bu sorgunun yürütme zamanı kimliği etrafında 10 saniye belirtilen kategorideki veritabanında 7000 kayıtları ve ~ 1000 Kayıt için

SELECT [Project1].[pintId1]   AS [pintId], 
[Project1].[pintId]   AS [pintId1], 
[Project1].[intProductId]  AS [intProductId], 
[Project1].[nvcSupplier]  AS [nvcSupplier], 
[Project1].[ nvcArticle]  AS [ nvcArticle], 
[Project1].[nvcBarcode]  AS [nvcBarcode], 
[Project1].[bIsActive]  AS [bIsActive], 
[Project1].[dtDeleted]  AS [dtDeleted], 
[Project1].[pintId2]   AS [pintId2], 
[Project1].[nvcName]   AS [nvcName], 
[Project1].[intCategoryId] AS [intCategoryId], 
[Project1].[ncProductType] AS [ncProductType], 
[Project1].[C1]    AS [C1], 
[Project1].[pintId3]   AS [pintId3], 
[Project1].[intProductItemId] AS [intProductItemId], 
[Project1].[intStorageId]  AS [intStorageId], 
[Project1].[dAmount]   AS [dAmount], 
[Project1].[mPrice]   AS [mPrice], 
[Project1].[dtModified]  AS [dtModified], 
[Project1].[pintId4]   AS [pintId4], 
[Project1].[nvcName1]   AS [nvcName1], 
[Project1].[bIsDefault]  AS [bIsDefault] 
FROM  (SELECT [Extent1].[pintId]   AS [pintId], 
[Extent1].[intProductId] AS [intProductId], 
[Extent1].[nvcSupplier] AS [nvcSupplier], 
[Extent1].[ nvcArticle] AS [ nvcArticle], 
[Extent1].[nvcBarcode]  AS [nvcBarcode], 
[Extent1].[bIsActive]  AS [bIsActive], 
[Extent1].[dtDeleted]  AS [dtDeleted], 
[Extent2].[pintId]   AS [pintId1], 
[Extent3].[pintId]   AS [pintId2], 
[Extent3].[nvcName]  AS [nvcName], 
[Extent3].[intCategoryId] AS [intCategoryId], 
[Extent3].[ncProductType] AS [ncProductType], 
[Join3].[pintId1]   AS [pintId3], 
[Join3].[intProductItemId] AS [intProductItemId], 
[Join3].[intStorageId]  AS [intStorageId], 
[Join3].[dAmount]   AS [dAmount], 
[Join3].[mPrice]   AS [mPrice], 
[Join3].[dtModified]  AS [dtModified], 
[Join3].[pintId2]   AS [pintId4], 
[Join3].[nvcName]   AS [nvcName1], 
[Join3].[bIsDefault]  AS [bIsDefault], 
CASE 
WHEN ([Join3].[pintId1] IS NULL) THEN CAST(NULL AS int) 
ELSE 1 
END AS [C1] 
FROM [ProductItem] AS [Extent1] 
INNER JOIN [Product] AS [Extent2] 
ON [Extent1].[intProductId] = [Extent2].[pintId] 
LEFT OUTER JOIN [Product] AS [Extent3] 
ON [Extent1].[intProductId] = [Extent3].[pintId] 
LEFT OUTER JOIN (SELECT [Extent4].[pintId]   AS [pintId1], 
[Extent4].[intProductItemId] AS [intProductItemId], 
[Extent4].[intStorageId]  AS [intStorageId], 
[Extent4].[dAmount]   AS [dAmount], 
[Extent4].[mPrice]   AS [mPrice], 
[Extent4].[dtModified]  AS [dtModified], 
[Extent5].[pintId]   AS [pintId2], 
[Extent5].[nvcName]   AS [nvcName], 
[Extent5].[bIsDefault]  AS [bIsDefault] 
FROM [Inventory] AS [Extent4] 
INNER JOIN [Storage] AS [Extent5] 
ON [Extent4].[intStorageId] = [Extent5].[pintId]) AS [Join3] 
ON [Extent1].[pintId] = [Join3].[intProductItemId] 
WHERE [Extent2].[intCategoryId] = 8 /* @p__linq__0 */) AS [Project1] 
ORDER BY [Project1].[pintId1] ASC, 
[Project1].[pintId] ASC, 
[Project1].[pintId2] ASC, 
[Project1].[C1] ASC 

:

ObjectSet<ProductItem> objectSet = ...; 
int categoryId = ...; 

var res = from pi in objectSet.Include("Product").Include("Inventory").Include("Inventory.Storage") 
where pi.Product.CategoryId == categoryId 
select pi; 

EF bu sql sorgusu oluşturulan:

Bu LINQ sorgusu yazdı .

FROM [ProductItem] AS [Extent1] 
INNER JOIN [Product] AS [Extent2] 
ON [Extent1].[intProductId] = [Extent2].[pintId] 
LEFT OUTER JOIN [Product] AS [Extent3] 
ON [Extent1].[intProductId] = [Extent3].[pintId] 
***LEFT OUTER JOIN (SELECT ....*** 

İçiçe LINQ sorgusunu değiştirmeye çalıştım ... Korkunç ... katılmak seçmiş, ama aynı SQL sorgusu outputted olsun: şuna bak eğer şaşırtıcı değildir.

Saklı yordamları kullanan bir çözüm benim için kabul edilemez çünkü SQL Compact veritabanı kullanıyorum.

+3

İngilizceniz o kadar da kötü değil :) İyi biçimlenmiş soru da. +1 – Aren

+1

Görüntüleri paylaşmak için http://imgur.com/ kullanabilirsiniz. – Steven

+2

İçindekiler ile neler var? Neden pi_Product.CategoryId == categoryId pi_? –

cevap

7

Include("Product").Include("Inventory").Include("Inventory.Storage") yapıyorsunuz ve neden bu kadar çok sayıda kaydın alındığını ve neden bu kadar büyük bir SQL sorgusunu görebildiğini merak ediyorsunuz? Lütfen Include yönteminin ne hakkında olduğunu anladığınızdan emin olun. Eğer o alt koleksiyonları yineleme zaman

var res = 
    from pi in objectSet 
    where pi.Product.CategoryId == categoryId 
    select pi; 

bu çok daha fazla sorgular neden olabilir yük Products, tembel Inventories ve Storages mümkün gönderilmek üzere edeceğini ancak unutmayın: Eğer daha basit bir sorgu istiyorsanız, lütfen şu adresi kullanın .

+0

+1 iyi nokta - Ürün: ProductItem (1: *) ve ProductItem: Envanter (1: *) ile, tek bir Ürün fazladan (muhtemelen gereksiz) bir sürü veri yüklemek .... hiç de şaşırtıcı değil .... –

0

Sorun şu ki, Depolama öğesindeki Envanter koleksiyonunda sorun var. Sorgunuz, belirtilen CategoryId için seçilen Ürün, Ürün Öğesi ve Envanter öğelerini sınırlayacaktır. Ancak, Depolama öğesi Envanter koleksiyonunu doldurmak için, sorgu aynı StorageId'leri (ve sonra bu ek Envanter kayıtları için karşılık gelen tüm ProductItem ve Ürün satırlarını kullanan tüm Envanter satırlarını döndürmelidir.

I Envanter koleksiyonunu Storage öğesinden kaldırarak veya ilgili olanları kaldırarak başlatınız.

İlgili konular