如何清洁&优化WCF OData服务生成的代码?

时间:2011-09-23 00:09:06

标签: sql entity-framework

我有一个OData Web服务,就访问和返回数据库中的数据而言,主要是OOTB。

我们看到的问题是,生成的代码非常复杂 - 并且不必要 - 复杂,并且在针对服务器执行时会造成巨大延迟。

例如:

SELECT 
[Extent1].[Id] AS [Id], 
N'ODATAModel.LatestFiguresView' AS [C1], 
N'EntityType,Name,RegistrationNumber,OfficeNumber,DateRegistered,...,Id' AS [C2], 
[Extent1].[EntityType] AS [EntityType], 
[Extent1].[Name] AS [Name], 
[Extent1].[RegistrationNumber] AS [RegistrationNumber], 
[Extent1].[OfficeNumber] AS [OfficeNumber], 
... Loads of other columns ...
,
N'' AS [C12]
FROM (SELECT 
      [LatestFiguresView].[Id] AS [Id], 
      [LatestFiguresView].[EntityType] AS [EntityType], 
      [LatestFiguresView].[Name] AS [Name], 
      [LatestFiguresView].[RegistrationNumber] AS [RegistrationNumber], 
      [LatestFiguresView].[OfficeNumber] AS [OfficeNumber], 
... Loads of those same columns ...

FROM [dbo].[LatestFiguresView] AS [LatestFiguresView]) AS [Extent1]
WHERE (N'Registered' = [Extent1].[RegistrationStatus]) 
    AND ((1 = [Extent1].[Reservation]) 
    OR (1 = (CASE WHEN ([Extent1].[Name] LIKE N'%White%') 
    THEN cast(1 as bit) 
    WHEN ( NOT ([Extent1].[Name] LIKE N'%White%')) 
    THEN cast(0 as bit) END)) 
    OR (1 = (CASE WHEN ([Extent1].[Sectors] LIKE '%Business%') 
    THEN cast(1 as bit) 
    WHEN ( NOT ([Extent1].[Sectors] LIKE '%Business%')) 
    THEN cast(0 as bit) END)) 
    OR ((1 = (CASE WHEN ... etc, etc ... END))))

正如您所看到的,有不必要的嵌套选择,WHERE子句包含对值进行冗余检查的负载(例如“CASE WHEN MyColumn LIKE'%Value%'THEN 1,而不是MyColumn LIKE'%Value%'那么0“

当然有一种方法可以在它到达数据库之前整理这个混乱?

1 个答案:

答案 0 :(得分:3)

当您使用Entity Framework从数据库中选择一个大对象图时,您会收到 - 正如您所看到的 - 通过将多个查询表连接在一起形成了大量数据。然后,“魔法”会在你的应用程序中重新出现,因为这个超大的结果集被剥离并被切碎回实体。

您将映射的每个列都将从数据库中选择。这很自然 - 你不能选择一半的实体。如果您选择LatestFiguresView,那么该视图中的每一列都会出现在您的选择语句中 - 如果您要检索订单上的产品,那么Product上的每个映射列都会显示在Order上。 SELECT [Column] FROM (SELECT [dbo].[Column] AS [Column])将出现在结果集中。

是的,实体框架总是SELECT * FROM MyTable。我无法告诉你为什么,但我猜它有助于代码安全性在一些边缘情况下,直接从表中选择会导致问题,或者它允许查询生成器更有效。你是对的,这些是“不必要的”,但我不认为它们会花费任何成本。我可以同时运行SELECT * (SELECT * FROM MyTable) tWHERE

最后,CASEWHERE语句由您的查询决定 - 没有看到它,或者完整的if x or y or (a & b)条款,很难发表评论(注意:我不是真的想要查看您的查询,我确定它不是很漂亮)。如果你有CASE那么事情会变得混乱。

我通常不担心{{1}}语句,因为它们在SQL中速度非常快。我再次假设这是一个代码安全决策,或者它允许更高效(更通用的?)查询生成器。

我建议您在查询分析器中运行它来对其进行基准测试并识别任何问题,然后编写自己的SQL并执行相同的操作。在很多情况下,编写存储过程比使实体框架编译查询更有效,但如果直接从具有多种条件的视图中选择将是其中一种情况,我会感到惊讶。