Как очистить и оптимизировать код, сгенерированный службой ODF WCF? - PullRequest
0 голосов
/ 23 сентября 2011

У меня есть веб-сервис OData, который в основном 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, когда MyColumn LIKE '% Value%' THEN 1, WHEN NOT MyColumn LIKE '% Value%' ТО 0 ")

Конечно, есть способ убрать этот беспорядок, прежде чем он попадет в базу данных?

1 Ответ

3 голосов
/ 23 сентября 2011

Когда вы выбираете большой граф объектов из своей базы данных, используя Entity Framework, вы получаете - как вы видите - огромный массив данных, сформированный путем объединения нескольких запрашиваемых таблиц вместе. Затем «волшебство» происходит снова в вашем приложении, поскольку этот негабаритный результирующий набор разбирается и измельчается обратно в объекты.

Каждый сопоставленный столбец будет выбран из базы данных. Это вполне естественно - вы не можете выбрать половину объекта. Если вы выбираете LatestFiguresView, то каждый столбец в этом представлении будет в вашем операторе выбора - и если вы извлекаете Продукты по заказу, то каждый сопоставленный столбец в Product & Order будет в наборе результатов. .

Да, Entity Framework всегда делает SELECT [Column] FROM (SELECT [dbo].[Column] AS [Column]). Я не могу сказать вам, почему, но я предполагаю, что это либо помогает с безопасностью кода в некотором граничном случае, когда выбор непосредственно из таблицы вызывает проблемы, либо позволяет генератору запросов быть более эффективным. Вы правы, что это «ненужно», но я не думаю, что они чего-то стоят. Я могу запустить SELECT * FROM MyTable и SELECT * (SELECT * FROM MyTable) t одновременно.

Наконец, операторы WHERE и CASE определяются вашим запросом - без его просмотра или полного предложения WHERE трудно комментировать (примечание: я действительно не хочу видеть ваш запрос, Я уверен, что это не красиво). Если у вас есть if x or y or (a & b), то все станет грязно.

Обычно я не беспокоюсь о CASE операторах, поскольку они невероятно быстры в SQL. Я бы снова предположил, что это либо решение по безопасности кода, либо оно позволяет более эффективный (более общий?) Генератор запросов.

Я бы посоветовал вам запустить это в Query Analyzer, чтобы сравнить его и выявить любые проблемы, а затем написать собственный SQL и сделать то же самое. Существует множество случаев, когда писать хранимые прокси более эффективно, чем Entity Framework для компиляции ваших запросов, но я был бы удивлен, если бы одним из таких случаев был выбор непосредственно из представления с несколькими условиями.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...