Тоже пробовал postgres.
Из неприятных моментов:
— все названия таблиц, колонок только маленькими буквами. Можно ли как-то его заставить использовать camelCase названия я так и не нашел. В Sql Server это можно, в Oracle можно, в MySql можно, почему в postgres нельзя — загадка.
— понятие collation такое ощущение что в postgres-е отсутствует, т.е. производить case insensitive сравнение строк легко нельзя (нужно либо использовать специальный тип, либо при сравнении использовать функции приведения к lowercase или uppercase)
— значительно меньшее кол-во IDE для разработки чем для того же MySql
— немного непривычный синтаксис для функций, отсутствие привычных хранимых процедур
Что очень понравилось:
— можно делать filtered индексы в отличие от MySql
— можно писать свои функции, причем на очень широком спектре языков — вплоть до javascript — в MySql такой возможности просто нет, а жалко.
Очень интересно было бы прочитать про примеры таких приложений, где «много потоков постоянно подписываются и отписываются от какого-то события».
Интересно, использует ли кто-то реально события в таких приложениях или все-таки другие методы (очереди сообщений, например)?
Где вы здесь видите получение ВСЕХ объектов Person (всех что есть в БД)? В этом методе сначала строится LINQ запрос (query), а затем по нему вытянутся из БД только нужные Person-ы. Или вы говорите о том, что само построение SQL запроса из ExpressionTree будет тормозить?
Вопрос в том, что вам, возможно, не нужны ВСЕ поля класса Person в результате — тогда можно выдавать какой-нибудь PersonView[] с нужными полями.
Я скажу так. EF — это фреймворк и это не только получение, но и сохранение данных. Как и любой фреймворк, он навязывает вам определенную архитектуру по работе с БД. В частности, паттерн UnitOfWork.
Если вы делаете общедоступным свой DbContext или методы, возвращающие IQuerable, вы подсаживаете все части своего приложения на логику работы ORM. Хотя это дает гибкость в получении и сохранении любых данных в любом месте вашего приложения, есть и весьма значительные минусы, например:
— у вас появляются похожие запросы в разных частях приложения. Приходится все равно делать что-то типа репозитория, чтобы избежать дублирования кода
— вы начинаете сохранять данные через DbContext.SaveChanges() в куче мест вашего приложения. Затем возникают сложные ситуации, где надо использовать транзакции, хранимые процедуры, определенную последовательность сохранения и т.п. Вам приходится все равно выносить всю эту логику из клиентского кода в репозиторий.
— вы понимаете, что EF — вообще отстой, делает очень неэффективные запросы, ест кучу памяти, при сохранении выдает вам какие-то странные и непонятные exception-ы и вообще начинает вас выводить из себя. А оказывается, что на него всё завязано и чтобы это переделать, надо переписать и ЗАНОВО ПРОТЕСТИРОВАТЬ 70% приложения. Вот тут вы начинаете по другому делать СЛЕДУЮЩЕЕ приложение :)
Это больше архитектурный вопрос. Многое зависит от вашего конкретного случая. Всякое решение имеет плюсы и минусы. IQuerable вносит дополнительную неопределенность в ваш слой доступа к данным, что лично мне не нравится. Я люблю определенность.
Что будет тормозить? Это же пример подхода к построению репозитория. Вся его прелесть в том, что вы можете оптимизировать этот метод фильтрации как угодно, а потребители этого метода ничего не заметят.
Зачем вам тогда репозиторй вообще? EF сам по себе представляет абстракцию, с которой вы работаете. Если вы возвращаете из репозитория IQuerable, то репозиторий по сути превращается в некий helper для DbContext.
С тем же успехом можно просто методы в ваш контекст добавлять и работать с ними.
Также проблема IQuerable в том, что вы перекладываете логику (включая всевозможные оптимизации) построения реального запроса к БД на потребителя вашего метода, т.к. он может накрутить на ваш IQuerable еще кучу всякой логики.
public Person[] FindPeople(PersonFilter filter)
{
using(var dbContext = new AppDbContext())
{
var query = dbContext.People;
if(filter.Age != null)
query = query.Where(p=>p.Age == filter.Age);
//Остальная фильтрация
...
return query.ToArray();
}
}
Смысл в том, что метод делает ровно то, что вы от него ждете — выдает вам из БД фильтрованный список записей. В параметры вы можете ему передавать поля фильтрации, пейджинга, сортировки и т.п. — все будет делаться в этом методе.
Сильно зависит от того, как вы используете LazyLoading. Внезапно получить ObjectDisposedException при работе с объектом, полученным из БД, не особо приятно.
Совет здесь один — освобождайте явно контекст, когда он вам 100% больше не нужен.
Из неприятных моментов:
— все названия таблиц, колонок только маленькими буквами. Можно ли как-то его заставить использовать camelCase названия я так и не нашел. В Sql Server это можно, в Oracle можно, в MySql можно, почему в postgres нельзя — загадка.
— понятие collation такое ощущение что в postgres-е отсутствует, т.е. производить case insensitive сравнение строк легко нельзя (нужно либо использовать специальный тип, либо при сравнении использовать функции приведения к lowercase или uppercase)
— значительно меньшее кол-во IDE для разработки чем для того же MySql
— немного непривычный синтаксис для функций, отсутствие привычных хранимых процедур
Что очень понравилось:
— можно делать filtered индексы в отличие от MySql
— можно писать свои функции, причем на очень широком спектре языков — вплоть до javascript — в MySql такой возможности просто нет, а жалко.
Интересно, использует ли кто-то реально события в таких приложениях или все-таки другие методы (очереди сообщений, например)?
Вопрос в том, что вам, возможно, не нужны ВСЕ поля класса Person в результате — тогда можно выдавать какой-нибудь PersonView[] с нужными полями.
Если вы делаете общедоступным свой DbContext или методы, возвращающие IQuerable, вы подсаживаете все части своего приложения на логику работы ORM. Хотя это дает гибкость в получении и сохранении любых данных в любом месте вашего приложения, есть и весьма значительные минусы, например:
— у вас появляются похожие запросы в разных частях приложения. Приходится все равно делать что-то типа репозитория, чтобы избежать дублирования кода
— вы начинаете сохранять данные через DbContext.SaveChanges() в куче мест вашего приложения. Затем возникают сложные ситуации, где надо использовать транзакции, хранимые процедуры, определенную последовательность сохранения и т.п. Вам приходится все равно выносить всю эту логику из клиентского кода в репозиторий.
— вы понимаете, что EF — вообще отстой, делает очень неэффективные запросы, ест кучу памяти, при сохранении выдает вам какие-то странные и непонятные exception-ы и вообще начинает вас выводить из себя. А оказывается, что на него всё завязано и чтобы это переделать, надо переписать и ЗАНОВО ПРОТЕСТИРОВАТЬ 70% приложения. Вот тут вы начинаете по другому делать СЛЕДУЮЩЕЕ приложение :)
С тем же успехом можно просто методы в ваш контекст добавлять и работать с ними.
Также проблема IQuerable в том, что вы перекладываете логику (включая всевозможные оптимизации) построения реального запроса к БД на потребителя вашего метода, т.к. он может накрутить на ваш IQuerable еще кучу всякой логики.
Смысл в том, что метод делает ровно то, что вы от него ждете — выдает вам из БД фильтрованный список записей. В параметры вы можете ему передавать поля фильтрации, пейджинга, сортировки и т.п. — все будет делаться в этом методе.
Совет здесь один — освобождайте явно контекст, когда он вам 100% больше не нужен.