запрос с использованием свойства внешнего ключа или свойства навигации? EF 4.1 - PullRequest
1 голос
/ 03 июля 2011

Я сопоставляю некоторые классы POCO с существующей базой данных с несколькими таблицами поиска, и мне было интересно, каков будет наиболее эффективный или рекомендуемый способ продолжения.

Допустим, есть класс модели Employee, которыйсопоставляется с таблицей Employee:

public class Employee
{
    public int ID { get; set }
    public string Name { get; set }

    [ForeignKey("Role")]
    public int RoleID { get; set }
    public virtual EmployeeRole Role { get; set }
}

, а класс / таблица EmployeeRole выглядит следующим образом:

public class EmployeeRole
{
    public int ID { get; set } // For instance: 1
    public string Description { get; set } // for instance: Manager
}

Я знаю, что не нужно явно объявлять внешний ключ RoleID, но на самом деле мне приходится выполнять довольно большое количество запросов, которые зависят от Employee, имеющего EmployeeRole от «Менеджера».

Теперь вопрос в том, что лучше с точки зрения сочетания эффективности,читабельность кода и «независимость данных»?Предполагая, что employees является IQueryable, только что извлеченным из хранилища:

  1. employees.Where(e => e.RoleID == 1);
  2. employees.Where(e => e.EmployeeRole.ID == 1);
  3. employees.Where(e => e.EmployeeRole.Description == "Manager");

2 и 3 имеют недостаток, заключающийся в том, что свойство навигации лениво загружается, но у 1 есть недостаток, заключающийся в том, что RoleID == 1 довольно бессмысленен и связан с текущим состоянием базы данных.

Как следуетЯ продолжаю?Есть ли вариант 4?

Ответы [ 2 ]

4 голосов
/ 03 июля 2011

Я предполагаю, что все 3 запроса дадут одинаковые результаты. По крайней мере, 1 и 2 должны выдавать один и тот же SQL. Вы можете увидеть сгенерированный оператор SQL, вызвав ToTraceString для экземпляра ObjectSet (я должен был бы посмотреть это, возможно, где-то спрятан).

- Изменить Я воссоздал вашу модель и обнаружил, что использовались следующие запросы (SQL Server). Вы должны привести запрос к System.Data.Objects.ObjectQuery, который предоставляет метод ToTraceString ().

employees.Where(e => e.RoleID == 1);
employees.Where(e => e.EmployeeRole.ID == 1);

// Both result in:
SELECT [Extent1].[Id] AS [Id], [Extent1].[Name] AS [Name], [Extent1].[RoleId] AS [RoleId]
FROM [dbo].[Employees] AS [Extent1]
WHERE 1 = [Extent1].[RoleId]

и

employees.Where(e => e.EmployeeRole.Description == "Manager");

SELECT  [Extent1].[Id] AS [Id], [Extent1].[Name] AS [Name], [Extent1].[RoleId] AS [RoleId]
FROM  [dbo].[Employees] AS [Extent1]
INNER JOIN [dbo].[Roles] AS [Extent2] ON [Extent1].[RoleId] = [Extent2].[Id]
WHERE N'Manager' = [Extent2].[Name]
0 голосов
/ 19 июля 2012

Немного поздно, но я с большим успехом ввел в свои таблицы понятие «флаги».Например, если вы знаете, что часто можете запрашивать у менеджеров, добавьте немного в таблицу под названием «Менеджер», и в своем коде просто выполните e.EmployeeRole.Manager и все готово.Сильно набрано и имеет реальное деловое значение.

...