2017-02-22 1 views
0

Вот моя модель:EntityFramework - нагрузка только последний ребенок из коллекции (проблемы с производительностью)

public partial class auctions 
{ 
    public int id { get; set; } 
    public virtual ICollection<auction_data> auction_data { get; set; } 
} 
public partial class auction_data 
{ 
    public int id { get; set; } 
    public int auction_id { get; set; } 
    public string title { get; set; } 
    public virtual auctions auctions { get; set; } 
} 

Каждый аукцион может иметь тысячи од auction_data элементы, прикрепленные к нему. Но я заинтересуют только в последнем из него:

var matchingAuctions = context.auctions.Where(a => /** some conditions **/); 
foreach (auctions auction in matchingAuctions) 
{ 
    var data = auction.auction_data.LastOrDefault(); // <---- takes very long time and memory when having large count of auction_data 
} 

Похоже, что EF загружает все auction_data в памяти, а затем возвращает последний. Вопрос в следующем: как я могу повысить производительность этого кода и не загружать все эти записи в память?

EDIT: некоторые сроки

DateTime t1 = DateTime.Now; 
var data = auction.auction_data.LastOrDefault(); 
DateTime t2 = DateTime.Now; 
TimeSpan diff = t2 - t1; // 8.8s 


DateTime t1 = DateTime.Now; 
var data = auction.auction_data.OrderByDescending(a => a.id).FirstOrDefault(); 
DateTime t2 = DateTime.Now; 
TimeSpan diff = t2 - t1; // 8.7s 

DateTime t1 = DateTime.Now; 
var data = auction.auction_data.Last(); 
DateTime t2 = DateTime.Now; 
TimeSpan diff = t2 - t1; // 8.7s 

int id = auction.id; 
DateTime t1 = DateTime.Now; 
var data = context.auction_data.Where(d => d.auction_id == id).OrderByDescending(d => d.id).FirstOrDefault(); 
DateTime t2 = DateTime.Now; 
TimeSpan diff = t2 - t1; // 0.06s 
+0

Вы можете полностью изменить вид и затем взять 'First()' вместо 'Last()' –

+0

Зачем вам когда-либо брать последнюю строку, когда не применяется заказ? _Define ... в последний раз? (наивысшее значение Id/last datetime?) _ –

+0

Также пробовал этот способ, но получил тот же результат – user3175253

ответ

2

Это нормально. Когда вы пишете auction.auction_data, он читает все auction.auction_data. Если бы я был вами, я бы сделал это для повышения производительности:

public partial class auctions 
{ 
    public int id { get; set; } 
    public int lastDataId { get; set;} 
    public virtual ICollection<auction_data> auction_data { get; set; } 
} 

и при вставке данных введите идентификатор как последний.

В качестве теста: у меня нет большой базы данных, чтобы проверить, но, может быть, changeing Last() вместо LastOrDefault() может halp вас. Я прочитал:

LastOrDefault - полезный метод. Она находит последний элемент в коллекции, которая соответствует условию

так, чтобы проверить Maching кондиционировать его нужно прочитать все записи, но возможно Last() не делает

+0

Пожалуйста, взгляните на мой вопрос (отредактированный) – user3175253

+0

Я не верил в 'OrderByDescending' с первого раза. Это почти то же самое. Но последний (хороший) способ - это то, что я предложил, вам нужно иметь идентификатор данных. ? –

+0

Еще одна вещь: 'var data = context.auction_data.Where (d => d.auction_id == id) .OrderByDescending (d => d.id) .FirstOrDefault();' не требуется ** Сортировка ** Это это только один элемент, когда id является первичным ключом –

0

Изменение:

var data = auction.auction_data.LastOrDefault(); 

к:

var data = auction.auction_data.OrderByDescending(x => x.id).FirstOrDefault(); 
+1

Я пробовал этот путь, но он почти не имеет значения (в моем тестовом случае 8,8 секунды против 8,7 секунд) – user3175253

+0

У вас есть правильные индексы на месте? Интересно, потому что EF работает очень хорошо, когда ваши таблицы базы данных индексируются правильно. – Stuart

+1

Да, у меня есть первичный ключ, установленный на ID.Как я уже упоминал, проблема заключается в том, что EF считывает всю таблицу в память и затем возвращает запись вместо чтения только одной строки из таблицы – user3175253

Смежные вопросы