2015-11-13 2 views
3

Я изучаю проблему с производительностью с использованием Entity Framework v6 за последние дни и не вижу способа решить проблему.Производительность Entity Framework с использованием другого типа доступа

У меня есть объект A (называемый компанией в приведенных ниже примерах), который содержит список вторых объектов B (материал в приведенных ниже примерах). Теперь я хочу захватить один кусок A и работать со всеми объектами типа B, которые содержатся в A. Для этого теста я использую 10000 штук B.

Когда я получаю объект, время отклика с сервера 5-10 секунд, используя один тип доступа, используя второй тип доступа, он использует только 0,2-0,3 секунды. Я просто не могу понять, почему.

Быстрая реакция (~ 0,2 до 0.3с): example1

using (var cont = new Context()) 
    { 
     Company C = cont.Companies.SingleOrDefault(o => o.ID == 18); 
     var mat = cont.Materials.Where(o => o.Company.ID == 18); 
     foreach (Material m in mat) { } // do stuff, does not matter 
    } 

Медленная реакция (~ 5 - 10 секунд): Пример 2.

using (var cont = new Context()) 
    { 
     Company C = cont.Companies.SingleOrDefault(o => o.ID == 18); 
     var mat = C.materials; // takes forever 
     foreach (Material m in mat) { } // do stuff, does not matter 
    } 

Существует вторая возможность для меня, чтобы замедлить реакция: ПРИМЕР3

using (var cont = new Context()) 
    { 
     cont.Configuration.LazyLoadingEnabled = false; 
     Company C = cont.Companies.Include(o => o.materials).SingleOrDefault(o => o.ID == 18); // takes forever 
     var mat = C.materials; // fast 
     foreach (Material m in mat) { } // do stuff, does not matter 
    } 

Я просто не могу решить проблему. Я использовал проблеск, чтобы посмотреть график. Проблема заключается в следующем: в первых двух примерах время выполнения SQL составляет всего ~ 100 мс. В примере 2 существует промежуток времени между последним исполнением SQL и конечным запросом в 5-10 секунд. В примере 3 оператор SQL совершенно другой (и сложный) и фактически занимает 5-10 секунд. Операторы SQL для примеров 1 и 2 точно такие же!

Есть ли у кого-нибудь идеи, что происходит?

Эти определения моих двух классов:

public class Company 
{ 
    public int Id { get; set; } 
    [Required] 
    public string Name { get; set; } 

    public virtual List<Material> Materials { get; set; } 

    public Company() 
    { 
    } 
} 

public class Material 
{ 
    public int Id { get; set; } 

    [Required] 
    public string Name { get; set; } 
    public string Producer { get; set; } 

    [Required] 
    public virtual Company Company { get; set; } 

    public Material() 
    { 
    } 
} 
+1

Вы уверены, что пример 1 и 2 производят Точно такой же запрос? Я считаю, что пример 1 имеет дополнительное место. Я считаю, что это быстрее, поскольку вы используете инструкцию Where для первичного ключа, который, скорее всего, является индексом - это может вызвать скорость example1 – MajkeloDev

+0

. Второй пример дает больше записей, поэтому, скорее всего, это не sql enginge slow, чтобы сделать этот запрос, это просто больше данные для отправки. – MajkeloDev

+0

На примерах 1 и 2 действительно два оператора SQL: сначала получен класс компании. После этого будут получены материалы. Оба оператора SQL точно одинаковы для примеров 1 и 2 (за исключением некоторых комментариев). –

ответ

1

После более тестирования я нашел решение, чтобы сделать все запросы одинаково быстро. Класс Material требует прямой ссылки на индекс класса Company. Я предполагаю, что доступ намного быстрее, потому что объект не нужно загружать каждый раз ?! Я до сих пор не понимаю, почему первый пример был быстрым с исходными классами. Или почему SQL-запросы выглядят точно так же в примерах 1 и 2 со значительной разницей в производительности.

public class Material 
{ 
    public int Id { get; set; } 

    [Required] 
    public string Name { get; set; } 
    public string Producer { get; set; } 

    [Required] 
    public int CompanyId { get; set; } // THIS IS NEW!!! 
    public virtual Company Company { get; set; } 

    public Material() 
    { 
    } 
} 
Смежные вопросы