2016-11-03 3 views
3

У меня типичный сценарий TPT (не спрашивайте меня, почему я сделал TPT, это был, вероятно, глупый выбор для начала), и я пытаюсь запустить простой граф запрос по типу BASE. , учитывая, что подсчет основан на базовом типе и на свойстве базового класса, я не могу понять, почему, но EF создает запрос COUNT(*), объединяя все производные типы вместе.Count Генерация запроса в наследовании типа «таб-за»

Классы что-то вроде этого:

public abstract class StudyCase { 
    public DateTime? DateSubmitted { get; protected set; } 
    public bool Deleted { get; set; } 
} 

public class StudyCaseStandard : StudyCase { 
// ... other stuff 
} 

public class StudyCaseReview : StudyCase { 
// ... other stuff 
} 

Мой запрос что-то вроде этого

SubmittedCasesCount = _context.Set<StudyCase>().Where(sc => !sc.Deleted).Count(sc => sc.DateSubmitted.HasValue); 

Это запрос генерируется EF (есть третий класс не показано выше, но видели в запрос):

SELECT 
    [GroupBy1].[A1] AS [C1] 
    FROM (SELECT 
     COUNT(1) AS [A1] 
     FROM (SELECT 
      [Extent1].[Id] AS [Id] 
      FROM [dbo].[StudyCases_Exacerbation] AS [Extent1] 
     UNION ALL 
      SELECT 
      [Extent2].[Id] AS [Id] 
      FROM [dbo].[StudyCases_Standard] AS [Extent2] 
     UNION ALL 
      SELECT 
      [Extent3].[Id] AS [Id] 
      FROM [dbo].[StudyCases_Review] AS [Extent3]) AS [UnionAll2] 
     INNER JOIN [dbo].[StudyCases] AS [Extent4] ON [UnionAll2].[Id] = [Extent4].[Id] 
     WHERE ([Extent4].[Deleted] <> 1) AND ([Extent4].[DateSubmitted] IS NOT NULL) 
    ) AS [GroupBy1] 
go 

Как вы можете видеть, что он делает все UNION й JOIN в то время как это было бы гораздо более эффективным (и только это необходимо), чтобы сделать простой подсчет, как это:

SELECT COUNT(1) AS [A1] 
FROM [dbo].[StudyCases] 
WHERE ([Deleted] <> 1) AND ([DateSubmitted] IS NOT NULL) 

Любая идея, как заставить EF для создания простых запросов, когда свойства производных классов не нужны или когда набор возврата является только набором базового класса (это может зависеть и от ключевого слова abstract в базовом классе, но EF должен иметь возможность материализовать прокси для абстрактного класса)?

+0

редактирования: изменил это ответ для форматирования кода –

ответ

2

Что запрос производится, если вы используете оператор выбора, чтобы вытащить только свойства базового класса, как показано ниже:

SubmittedCasesCount = 
    _context 
     .Set<StudyCase>() 
     .Select(sc => new { Deleted = sc.Deleted, DateSubmitted = sc.DateSubmitted }) 
     .Where(anon => !anon.Deleted) 
     .Count(anon => anon.DateSubmitted.HasValue); 

Edit: Грустно выше производит тот же запрос, единственное другое решение, которое я нахожусь осознает делает необработанный запрос SQL, что-то вроде:

int count = context.Set<StudyCase> 
        .FromSql("SELECT Deleted, DateSubmitted FROM dbo.StudyCases") 
        .Where(sc => !sc.Deleted).Count(sc => sc.DateSubmitted.HasValue) 
        .Count(); 
+0

к сожалению, это точно такой же запрос ... – Tallmaris

+0

это позор, я редактировал с другим способом достигая этого, хотя несколько менее изящный. –

+0

Пользовательский запрос был тем направлением, в котором я не хотел идти, хотя мне кажется единственной альтернативой ... – Tallmaris