Первое, что вы можете сделать, это отключить отслеживание изменений, потому что вы не меняете данные в своем коде. Это предотвращает привязку загруженных объектов к контексту:
Для DbContext
(EF> = 4.1):
var inputs = contex.AIMRInputs.AsNoTracking()
.Where(x => x.Input_Type == 1);
И
var data = contex.Values.AsNoTracking()
.Where(x => x.InputID == input.InputID)
.OrderBy(x => x.TimeStamp)
.ToList();
Редактировать
Для EF 4.0 вы можете оставить свои запросы такими, какие они есть, но добавить следующие две первые строки в блоке using
:
contex.AIMRInputs.MergeOption = MergeOption.NoTracking;
contex.Values.MergeOption = MergeOption.NoTracking;
Это отключает отслеживание изменений для ObjectContext
.
Редактировать 2
... особенно в связи с комментарием @James Reategui ниже, что AsNoTracking
уменьшает объем памяти:
Это часто верно (как в модели / запросе этого вопроса), но не всегда! На самом деле использование AsNoTracking
может быть контрпродуктивным в отношении использования памяти.
Что делает AsNoTracking
, когда объекты материализуются в памяти?
Во-первых: он не присоединяет сущность к контексту и, следовательно, не создает записи в менеджере состояний контекста. Эти записи занимают память. При использовании POCO записи содержат снимок значений свойств объекта, когда он был впервые загружен / присоединен к контексту - в основном копия всех (скалярных) свойств в дополнение к самому объекту. Таким образом, потребляемая память занимает (примерно) вдвое больше размера объекта, когда AsNoTracking
не применяется.
Второе: с другой стороны, когда сущности не привязываются к контексту, EF не может использовать преимущество сопоставления идентификаторов между значениями ключей и ссылочными идентификаторами объектов. Это означает, что объекты с одним и тем же ключом будут материализованы несколько раз, что потребляет дополнительную память, а без использования AsNoTracking
EF обеспечит материализацию объекта только один раз для значения ключа.
Второй момент становится особенно важным, когда загружаются связанные объекты. Простой пример:
Скажем, у нас есть сущность Order
и Customer
, и у заказа есть один клиент Order.Customer
. Скажем, объект Order
имеет размер 10 байт, а объект Customer
- 20 байт. Теперь мы запускаем этот запрос:
var orderList = context.Orders
.Include(o => o.Customer).Take(3).ToList();
И предположим, что для всех 3 загруженных заказов назначен один и тот же клиент. Поскольку мы не отключили отслеживание, EF материализуется:
- 3 порядка объектов = 3x10 = 30 байт
- 1 объект клиента = 1x20 = 20 байт (поскольку контекст признает, что клиент одинаков для всех 3 заказов, он материализует только один объект клиента)
- 3 записи снимка порядка с исходными значениями = 3x10 = 30 байт
- 1 запись снимка клиента с исходными значениями = 1x20 = 20 байт
Сумма: 100 байт
(Для простоты я предполагаю, что записи контекста со скопированными значениями свойств имеют тот же размер, что и сами сущности.)
Теперь мы запускаем запрос с отключенным отслеживанием изменений:
var orderList = context.Orders.AsNoTracking()
.Include(o => o.Customer).Take(3).ToList();
Материализованные данные:
- 3 заказа объектов = 3x10 = 30 байт
- 3 (!) Объекта клиента = 3x20 = 60 байт (без сопоставления идентификаторов = несколько объектов на ключ, все три объекта клиента будут иметь одинаковые значения свойств, но они по-прежнему три объекта в памяти)
- Нет записей моментальных снимков
Сумма: 90 байт
Таким образом, при использовании AsNoTracking
запрос потребляет на 10 байт меньше памяти.
Теперь тот же расчет с 5 заказами (Take(5)
), снова все заказы имеют одного и того же клиента:
Без AsNoTracking
:
- 5 заказов объектов = 5x10 = 50 байт
- 1 объект клиента = 1x20 = 20 байт
- 5 записей снимка порядка с исходными значениями = 5x10 = 50 байт
- 1 запись снимка клиента с исходными значениями = 1x20 = 20 байт
Сумма: 140 байт
С AsNoTracking
:
- 5 заказов объектов = 5x10 = 50 байт
- 5 (!) Объектов клиента = 5x20 = 100 байт
- Нет записей моментальных снимков
Сумма: 150 байт
На этот раз использование AsNoTracking
было на 10 байт дороже.
Приведенные выше цифры очень грубые, но где-то точка безубыточности, где использование AsNoTracking
может потребовать большеmemory.
Разница в потреблении памяти между использованием AsNoTracking
или не сильно зависит от запроса, отношений в модели и конкретных данных, которые загружаются запросом.Например: AsNoTracking
всегда будет лучше в потреблении памяти, когда заказы в приведенном выше примере (или в основном) имеют разных клиентов.
Вывод: AsNoTracking
в первую очередь предназначен как инструмент для улучшения запроса производительность , а не использование памяти.Во многих случаях он также будет занимать меньше памяти.Но не удивляйтесь, если конкретному запросу требуется больше памяти с AsNoTracking
.В конце концов, вы должны измерить объем памяти для принятия твердого решения в пользу или против AsNoTracking
.