2015-08-19 2 views
1

Сначала я использую код EF6, чтобы выполнить запрос, который вытягивает большой объем данных для обработки с параллельным графическим процессором. Запрос linq возвращает IEnumerable.Как ускорить IEnumerable <T> доступ к базе данных

IEnumerable<DatabaseObject> results = (from items in _myContext.DbSet 
          select items).Include("Table1").Include("Table2"); 

Теперь мне нужно выполнить статистический анализ полного набора данных и представить результат пользователю.

К сожалению, из-за огромного размера возвращаемых данных просто выполняется results.ToList() занимает очень много времени, чтобы завершить ... и я даже не начал распараллеливать обработку данных!

У меня есть что-нибудь, что я могу сделать, чтобы сделать это более эффективным, чем сокращение объема данных, которые вытаскивают? Это не вариант, поскольку это полный набор данных, которые необходимо обработать.

EDIT 1

Мой текущий код первого заключается в следующем:

public class Orders 
{ 
    [Key] 
    public virtual DateTime ServerTimeId 
    { 
     get; 
     set; 
    } 

    public string Seller 
    { 
     get; 
     set; 
    } 


    public decimal Price 
    { 
     get; 
     set; 
    } 


    public decimal Volume 
    { 
     get; 
     set; 
    } 

    public List<Table1> Tables1{ get; set; } 


    public List<Table2> Table22{ get; set; } 
} 

Хотя не используя .INCLUDE мой запрос ускоряет значительно, если я не использую .INCLUDE ("Tables1) .INCLUDE ("Tables2") эти поля null в конечном итоге для этого запроса:

var result = (from items in _context.DbOrders 
         select orderbook).Include("Tables1").Include("Tables2") 

В моей DbContext я определил:

public DbSet<Orderok> DbOrders { get; set; } 

Если есть способ заставить Ef6 для заполнения этих таблиц без использования .INCLUDE, то я был бы очень рад, если бы кто-то мог поручить мне.

+0

Можете ли вы работать партиями? Как взять первые 100, начать обработку, пропустить 100 принять 100, добавить эти данные в обработку, пропустить 200 принять 100 и так далее? – Andrei

+0

Это может сработать. Что было бы лучше, если бы я смог преобразовать блоки дискретных партий данных в непрерывный поток; скажем, IObservable , холодный поток и трубу к процессору обработки в реальном времени. возможно ли это? Как это будет реализовано? Затем я мог обработать поток через окно с регулируемым размером данных. – guerillacodester

+0

Основная идея, которая приходит в голову, состоит в том, чтобы обернуть ваш запрос в какой-то итератор, что-то, что реализует IEnumerable, и для каждого следующего вызова он дает вам еще одну партию данных – Andrei

ответ

0

Вы можете загрузить основную таблицу, DbOrders и таблицы ребенка отдельно в контекст:

_myContext.Configuration.ProxyCreationEnabled = false; 

_myContext.DbOrders.Load(); 
_myContext.Table1.Load(); 
_myContext.Table2.Load(); 

Теперь контекст полностью заряжен с данными вам нужно. Надеюсь, вы не столкнетесь с исключением из памяти (потому что тогда весь подход рушится).

Entity Framework excecutes отношения FixUp, что означает, что она заполнит навигационные свойства DbOrders.Table1 и DbOrders.Table1.

Отключение создания прокси имеет две причины:

  • материализованная объекты будут как легкий как можно
  • Ленивая загрузка отключена, в противном случае он будет срабатывать при доступе к навигации собственности.

Теперь вы можете продолжать работу остроумие данных путем доступа к Local коллекции:

from entity in _myContext.DbOrders.Local 
... 

Далее можно попытаться ускорить О.П. процесс unmapping все поля базы данных, которые вам не нужны. Это приводит к меньшему набору результатов SQL, и материализованный объект будет еще легче.Чтобы достичь этого, возможно, вам нужно создать выделенный контекст.