C#Entity Framework 4导致性能下降的导航属性
我对这个问题中缺乏细节表示歉意 - 我需要帮助的第一件事就是知道在哪里寻找更多细节。C#Entity Framework 4导致性能下降的导航属性
我有enity框架4导航性能的问题在提交更改时显然导致性能不佳:
this.ObjectContext.SaveChanges();
正在30+秒的时候,导航性能(收益表)中的一个包含约8000行(其是不是很多,所以应该罚款)。
我已经使用了SQL事件探查器,并可以看到EF发出SELECT * FROM收据,它是非常缓慢:
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(receipt)
引起的延迟加载问题。因为在该行之前invoice.Receipts是空的,并且为了添加到收据,它必须首先加载收集。但这并不能解释为什么它通过warehouseId = 1进行选择,何时应该通过invoiceId进行选择。
编辑2:
我已通过替换在该方法中,可直接SQL命令的EF代码“固定”的问题。这不是一个好主意 - 当我有一个完美的ORM时,我不应该把SQL抛出。但是现在我还是不明白,为什么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);
}
}
}
因为这是一个插入,它刷新你的对象,通过选择价值背部和重新建的对象。现在让我来回答你的问题,你布局:
你不应该需要调试,而不是
SaveChanges()
,你看到的可能就是将没有多大意义反正。它实际上并没有在做
select * from Receipts
。它正在做一个select * from Receipts where WarehouseId = 1
。因此,出于某些原因,您反对的是将仓库的所有收据与Id一同提取。这可能取决于很多事情,您现在无法进入。但是要开始的一个地方是检查应用程序框和数据库框之间的ping速度。还要检查数据库框中的RAM是否已满。那就是我要开始的地方,这就是你所描述的通常的问题。
调试EF的好工具是EF Profiler。 http://efprof.com这将比SQL事件探查器更有帮助。
您的问题与“仓库”实体上的“导航属性”有关。删除此导航属性。关系仍然存在,但在创建收货单位时,它不再查询该仓库的所有收货。我有同样的问题,这解决了我的问题。
您能否详细说明一下?这个问题仍然没有解决(它通过使用直接的sql插入语句来应用“修复”)。我所有的POCO类都是自动生成的,因此它们包含每个FK关系的导航属性。你有一个网页的URL描述删除导航属性? (例如,我怎么才能知道什么收据。仓库是当我没有财产了)。谢谢 – 2011-05-13 22:32:38
您是否打开了延迟加载?如果是这样,当您访问相关导航属性时,它将触发对WarehouseDetails
和Receipts
表的查询。我总是确保关闭延迟加载,这样我就不会无意中触发查询。
+1表示efprof.com - 我没有意识到这一点。 -1的成本,305美元??哇 – 2011-04-05 02:30:27
重申你的观点#2。我试图找到原因 - 这可能是问题所在。我确实发现导航属性没有被正确使用,但是修复这个问题并没有删除select *查询 – 2011-04-05 02:32:22
我发现它通过注释掉它,直到它发挥作用。但我不能从代码中看到为什么EF发出select查询。 – 2011-04-05 03:51:18