Факты:
- У меня есть настольное приложение, поддерживаемое базой данных SQL CE.
- Многие таблицы доступны только для чтения.
- Я использую EF Code First для генерации базы данных и обработки грубых операций.
- Я обычно оставляю один DbContext открытым для всего сеанса и располагаю при выходе из приложения. (Примечание: я пытался создавать новый DbContext чаще и обнаружил, что производительность на самом деле была хуже. Кроме того, мне никогда не нужно откатывать изменения.)
- Для некоторых из моих сущностей я добавил несколько геттеров для предоставления необходимых данных, полученных из других свойств сущности. Некоторые из этих геттеров фактически выполняют запросы LINQ (что, я подозреваю, является частью моей проблемы).
Все работает, но теперь я понимаю, что мне нужно провести некоторую оптимизацию. Производительность в целом несколько вялая, но меня особенно беспокоит один действительно гигантский запрос, который пользователи должны периодически запускать, который сводит практически всю базу данных в одну таблицу, а затем выводит ее в текстовый файл с разделителями. Этот запрос занимает гораздо больше времени, чем хотелось бы.
Одна идея, которую я имею для ускорения, состоит в том, чтобы хранить все, что доступно только для чтения, в List
вместо того, чтобы извлекать это из моего DbContext каждый раз, когда мне это нужно. Сложность в том, что, хотя я мог бы легко получить все свои Car
сущности из DbContext и сохранить их в списке, как бы я гарантировал, что все «вспомогательные свойства», такие как public virtual ICollection<Wheel> Wheels { get; set; }
или public virtual Engine Engine { get; set; }
, будут сохранены также? Бесполезно выполнять итерацию по всем Car
сущностям, если все связанные сущности также не повторяются.
Другая идея, которая у меня есть для повышения производительности, заключается в том, чтобы предложить способ кэширования геттеров, которые наиболее интенсивно используют процессор. Как я упоминал выше, некоторые из моих геттеров фактически выполняют запросы LINQ. Я знаю, что это снижает производительность, но поскольку некоторые из них зависят от данных, которые могут измениться, кэширование становится довольно сложным. У меня такое чувство, что потребуется реализация INotifyPropertyChanged
.
То, что я хотел бы, - это стратегия повышения производительности без отбрасывания всего хорошего, что EF уже делает для меня. Нет смысла сохранять что-либо в списке, например, если EF уже итерировал список и не будет повторять список снова, пока он не устареет.
Учитывая мою конкретную ситуацию и описанную выше историю, какую стратегию (ы) вы порекомендуете ускорить мое приложение?
Разъяснение
Как я уже писал в комментариях ниже ...
Для большого запроса я перебираю все свои сущности (помещая каждую в List<TEntity>
), затем выполняю гигантское объединение, затем выбираю нужные мне данные. Для этого окончательного выбора некоторые данные являются необработанными (базовое свойство объекта), а некоторые рассчитываются (получатель свойства, который зависит от базовых свойств объекта). Для вычисляемых свойств иногда используются запросы LINQ. Таким образом, большая часть тяжелой работы выполняется в C #, а не через базу данных (которая основана на файлах и представляет собой SQL CE).
Для всего остального в моем приложении. Я напрямую запрашиваю базу данных, когда это возможно, и не пытаюсь что-либо кэшировать. Если бы я мог найти способ полностью кэшировать все, что доступно только для чтения, в память, я должен был бы поверить, что это улучшило бы производительность, но я не совсем понимаю, как это сделать, учитывая, что (1) у меня есть объекты, которые хранят другие сущности и (2) сущности имеют геттеры, некоторые из которых выполняют запросы.