C # Entity Framework 4 Свойства навигации, вызывающие низкую производительность при фиксации

Прошу прощения за отсутствие подробностей в этом вопросе - первое, в чем мне нужна помощь, это знать, где искать более подробную информацию.

У меня есть проблема с навигационными свойствами enity framework 4, по-видимому, вызывающая низкую производительность при фиксации изменений:

this.ObjectContext.SaveChanges();

Требуется 30+ секунд, когда одно из свойств навигации (таблица квитанций) содержит около 8000 строк (что немного, так что должно быть хорошо).

Я использовал профилировщик SQL и вижу, что EF выдает команду select * from Receipts, и это очень медленно:

exec sp_executesql N'SELECT 
[Extent1].[Id] AS [Id], 
// full field list cut for brevity 
FROM [dbo].[Receipts] AS [Extent1]
WHERE [Extent1].[WarehouseId] = @EntityKeyValue1',
N'@EntityKeyValue1 int',@EntityKeyValue1=1

На данный момент я даже не могу понять , почему ему нужно выбирать все строки из этой таблицы при вызове ObjectContext.SaveChanges ().

Ему действительно нужно вставить 1 строку в эту таблицу, но это не объясняет, почему сначала выполняется выборка всех, и не объясняет, почему этот выбор занимает так много времени (тот же запрос в диспетчере запросов занимает <1 секунды )

Итак, мой вопрос прямо сейчас - я еще точно не знаю, в чем проблема - это:

  • Где / как я могу найти более подробную информацию о проблеме? Я не могу выполнить отладку в ObjectContext.SaveChanges (), поэтому не знаю, что внутри него происходит.
  • Почему EF пытается выбрать * из квитанций?
  • Почему так медленно? Тот же самый запрос, скопированный + вставленный в диспетчер запросов, выполняется почти мгновенно

РЕДАКТИРОВАТЬ:

Я подтвердил, что это код квитанции, который работает медленно, закомментировав вызов этого метода:

    private void AddReceipt(PurchaseInvoice invoice, 
                               PurchaseInvoiceLine invoiceLine)
    {
        if (invoice != null && invoiceLine != null)
        {
            Product product = invoiceLine.Product;
            if (product != null)
            {
                Receipt receipt = new Receipt{ foo = bar };
                WarehouseDetail detail = new WarehouseDetail{ foo = bar };
                receipt.WarehouseDetails.Add(detail);
                invoice.Receipts.Add(receipt);
            }
        }
    }

Но я все еще не могу понять, почему это заставляет EF выдавать этот запрос select *.

Я считаю, что это может быть проблема с отложенной загрузкой, вызванная invoice.Receipts.Add (чек) . Потому что перед этой строкой invoice.Receipts пусто, и для того, чтобы добавить .Add в Receipts, она должна сначала загрузить коллекцию. НО это не объясняет, почему он выбирается с помощью inventoryId = 1, когда он должен выбираться по invoiceId.

РЕДАКТИРОВАТЬ 2:

Я «исправил» проблему, заменив код EF в этом методе прямым SQL команды. Это не лучшая идея - я не должен бросать SQL, когда у меня есть совершенно хорошая ORM. Но прямо сейчас я все еще не понимаю, почему EF выполнял запрос select *

    private void AddReceipt(PurchaseInvoice invoice, 
                               PurchaseInvoiceLine invoiceLine)
    {
        if (invoice != null && invoiceLine != null)
        {
            Product product = invoiceLine.Product;
            if (product != null)
            {
                Receipt receipt = new Receipt{ foo = bar };
                WarehouseDetail detail = new WarehouseDetail{ foo = bar };
                int id = SqlHelper.AddWarehouseDetail(detail);
                receipt.WarehouseDetailId = id;
                SqlHelper.AddReceipt(receipt);
            }
        }
    }
9
задан JK. 6 April 2011 в 03:44
поделиться