Прошу прощения за отсутствие подробностей в этом вопросе - первое, в чем мне нужна помощь, это знать, где искать более подробную информацию.
У меня есть проблема с навигационными свойствами 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 секунды )
Итак, мой вопрос прямо сейчас - я еще точно не знаю, в чем проблема - это:
РЕДАКТИРОВАТЬ:
Я подтвердил, что это код квитанции, который работает медленно, закомментировав вызов этого метода:
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);
}
}
}