Как стать автором
Обновить

Комментарии 35

Разве C# программист не должен вбить в себя привычку прописывать AsNoTracking везде, кроме мест, где этого быть не должно?

Я обычно никогда не прописывал, просто потому что обычно в "сыром" виде сущности EF в доменной модели не нужны. Их обычно тут же преобразуют в объекты домена, как-то аггрегируют и т.д.

То есть через .Select(x => new Dto....) получаете новый объект? Разве в таком случае не следует также отключать отслеживание для быстродействия?

В таком случае объект ef даже не создаётся, поэтому и отключать нечего. А в общем имеет смысл делать две модели, одну для запросов на чтение без трекинга, и на запись с трекингом

Почему не создаётся? Там пулинг по дженерику?

А, все,понял, акцент на слове ef.

в таком случае нет смысла отключать трэйкинг, ибо он и не будет использоваться (он работает только если напрямую доставать объекты классов из базы)

Откуда программисту на С# вообще узнать о AsNoTracking если он работал только с NHibernate, а про EF слышит только на презенташках/новостях от MS ?

Молодёж и подавно не знает об msdn

Если человек пользуется технологией, но не знает, как она работает, то проблема явно не в трекинге или другом фреймворке. Молодежь также не знает, что такое nhibernate, поскольку все туториалы предлагают использовать ef. Если только не заниматься археологией. А понятние о трекинге всплывает довольно быстро.

Что-то я не понял, в таблицах везде написано, что WithoutTracking дольше работает, чем WithTracking. Данные перепутаны местами?

Да, похоже на то... Переставлял для удобства анализа. Сейчас перезалью результаты)

А по сути да, обычно редко когда делают коллекции прямо вот из сущностей EF. Делают из них DTO, а потом бизнес-объекты. А если нужно что-то заменить в базе, то заново читают из БД сущность с тем же id, что у той, которая в бизнес-объекте, и её уже изменяют и сохраняют обратно. Держать в памяти тонны сущностей EF в любом случае плохая практика. Ну, если только вы их не планируете так же массово изменять и писать обратно в БД.

Это здорово, что вы написали большую статью с бенчмарками.. но это базовая функциональность EF Core. Банально заходим в msdn и читаем

Запросы без отслеживания полезны, если результаты используются в сценарии только для чтения. Обычно они быстрее выполняются, так как нет необходимости настраивать сведения об отслеживании изменений.

Бенчмарк конечно наглядный, но стоило развить тему и так же написать какая база, сколько каких свойств было у запрашиваемых сущностей, каких типов, загружались ли связанные сущности по Foreign Key. Хотя такие бенчмарки тоже уже есть. В общем это обычный непримечательный случай траблшутинга с не очень понятными вводными, который не раз уже описывался на Хабре.

Интерес в комментариях же из-за низкого порога вхождения в язык, и большого количества нахватавшихся по верхам неофитов.. я бы советовал прочесть тот же Entity Framework Core in Action, тем более есть отличный перевод от dotnet.ru

Интерес личный был именно в том, "насколько"?
Запилил, поделился :)
Мне кажется именно в этом цель сообщества

На Хабре требования к качеству материала весьма высоки... Господа программисты тут оооочеень разборчивы... )

Давно уже есть Queryable Extensions

ProjectTo<ProductDTO>(configuration)

вместо

Select(x => _mapper.Map<ProductDTO>(x))

Давно есть, использую) Закинул тут для большей наглядности :)

А насколько это быстрее/лучше по памяти чем Dapper?

Интересно было бы сравнить такой вариант по скорости с dapper

Вопрос в том как и что сравнивать.. билдить запрос из модели? a кэшировать expression tree? или в обоих случаях сырым запросом? С параметрами или конкатенацией? Ещё бы проконтролировать что БД один и тот же план запроса использует во всех случаях.

После spring приложений дали поддерживать проект на EF. Честно говоря это дикий ужас, кто эти люди, которые предлагают писать бэк на этом...

хах, знакомо :)
В прошлом копался в NHibernate, но переезд был быстр и понятен.
Тут можно развернуться по-сути, особенно если нужно "Побыстрее и еще вчера"

Могу сказать тоже самое про spring. Ощущения субъективны, так что поменьше пафоса)

EF шикарный, просто лучший! NHibernate -- калька с Hibernate, вот это действительно был ужас, я с дрожью вспоминаю проекты на нём, очень тяжёлые и монструозные решения, но тогда и альтернатив особо не было. Сейчас же, на EF писать прям кайф. Я не знаю что там за "дикий ужас" вы узрели, но либо перед вами там так наговнокодили, что даже умудрились EF через одно место использовать, или у вас просто религиозные шоры, аля, спринг уан лав, остальное всё УГ — тут уже ничего не попишешь. Ведь что для настоящего инженера важно? Правильно, объективность в топку, цвет фломастеров наше всё :)

Да там понаписали костылей до меня, что проект на VisualStudio даже не собирается, только под Rider можно запустить. Тут в целом наверное претензия наверное не к EF, а в целом .net платформе, если не legacy проект выглядит ужасно. Но скорее всего это разработчики такие веселые были. Помимо спринга еще писал на Django. Там тоже как то всё намного понятнее

про Hibernate и в спринге хорошего сказать не могу - слишком много приносит ошибок, которые на первый взгляд кажутся неадекватными

EF шикарный,

EF Core совсем даже не шикарный.

Даже в 7-ой версии не сделано то, что должно было быть реализовано ещё в самом первом релизе: Complex Types\Value Objects, нормальная поддержка стандартных SQL-функций типа MIN\MAX и т.д.

просто лучший!

Но, возможно, действительно лучший в своём классе. Как это ни печально.

Сейчас же, на EF писать прям кайф.

EF Core до 3.1 был абсолютно ужасен. Одному проекту с моим участием сильно повезло, что дедлайн релиза был через пару месяцев после выхода 3.1 и мы миновали основные капуты типа множественных запросов вместо JOIN.

Вообще не понятно, как после всего опыта разработки оригинального EF для .NET Framework можно было так накосячить.

Даже в 7-ой версии не сделано то, что должно было быть реализовано ещё в самом первом релизе: Complex Types\Value Objects, нормальная поддержка стандартных SQL-функций типа MIN\MAX и т.д.

Не понимаю о чём вы, объекты-значения поддерживаются давно. Мы их используем. Min/Max тоже используем, и другие агрегатные функции.

Но, возможно, действительно лучший в своём классе. Как это ни печально.

Он действительно решает свою задачу. Но! Я заметил, что многие от ORM ожидают поддержки на уровне SQL, а такие ожидания ошибочные. Все попытки заменить SQL из всех, что я видел вообще во многих платформах -- ущербные, и неправильные. Зачем? Не нужно этого.

Вообще не понятно, как после всего опыта разработки оригинального EF для .NET Framework можно было так накосячить.

После перехода на Core, ЕF многое потерял, это правда. Но и приобрёл не мало. Концепция изменилась, расширилась поддержка типов СУБД.

В целом, по факту реализованных проектов могу сказать со 100% уверенностью. Это EF очень удобный инструмент для комфортной и быстрой разработки. И он ни в коем случае не лишает разработчика писать SQL-запросы, можно заменить LINQ на RAW SQL, и даже смешивать их. Что позволяет решать любые задачи, задачи любой сложности. Нет никаких ограничений.

Единственная проблема до версии EF 7 состоит в том, что нельзя было делать выборки в любые типы данных, проекции из SQL. Как в Dapper. И приходилось где-то использовать Dapper вместе с EF. Но начиная с EF 8, ситуация изменилась. Я ещё не пробовал, но вроде как Dapper больше будет не нужен.

Даже в 7-ой версии не сделано то, что должно было быть реализовано ещё в самом первом релизе: Complex Types\Value Objects, нормальная поддержка стандартных SQL-функций типа MIN\MAX и т.д.

Не понимаю о чём вы, объекты-значения поддерживаются давно. Мы их используем.

Вот об этом:

https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-8.0/whatsnew#value-objects-using-complex-types

Всё это должно было быть реализовано в самой первой версии EF Core, а не в 8-ой.

Min/Max тоже используем,

Вот здесь, 3-е место:

https://habr.com/ru/companies/pvs-studio/articles/766948/

и другие агрегатные функции.

Для Microsoft SQL Server функций поддерживается много. А для SQLite, например, из стандартных математических в 7-ой есть только ABS, MAX, MIN, ROUND. И те не работают, так как см. выше...

Он действительно решает свою задачу.

Вы путаете "решает свою задачу" с "альтернативы отсутствуют".

Но! Я заметил, что многие от ORM ожидают поддержки на уровне SQL, а такие ожидания ошибочные.

Почему ? Есть какие-то концептуальные препятствия ?

В целом, по факту реализованных проектов могу сказать со 100% уверенностью. Это EF очень удобный инструмент для комфортной и быстрой разработки.

Давайте я процитирую свой исходный комментарий:

"EF Core до 3.1 был абсолютно ужасен. Одному проекту с моим участием сильно повезло, что дедлайн релиза был через пару месяцев после выхода 3.1 и мы миновали основные капуты типа множественных запросов вместо JOIN"

Но начиная с EF 8, ситуация изменилась.

Как хорошо-то. Через 7+ лет наконец-то сделали базовую фичу, которая должна была быть ещё в самом первом релизе.

А ещё советую узнать про ExecuteUpdate и ExecuteDelete.

Хех, я видел пример, когда один флаг увеличивал быстродействие в 300 раз.

IEnumerable или IQueryable

Наверное, с БД работали через первый (IEnumerable), а не через второй, и в итоге в приложение тянулась вся таблица, я прав? :))

установить это значение по-умолчанию как AsNoTracking

Если в коде есть разделение ответственности на команды и запросы, то можно выделить 2 интерфейса для контекста:

public interface IDbReadOnly : IDisposable, IAsyncDisposable
{
  IQueryable<Order> Orders { get; }
  IQueryable<Product> Products { get; }
  // ...

  IQueryable<T> Query<T>() where T : class, IModel;
}

public interface IDb : IDbReadOnly
{
  void Add<T>(T entry) where T : class, IModel;
  void Remove<T>(T entry) where T : class, IModel;
  void Attach<T>(T entry) where T : class, IModel;

  Task SaveAsync(CancellationToken cancellationToken = default);
}

public class AppDb : DbContext, IDb
{
  // ...
}

Соответственно, запросы используют IDbReadOnly, для которого на уровне DI контейнера включено AsNoTracking.

встречаются с множеством прелестей этого инструмента:

  • Написание хранимок и прочее...

Всмысле написание хранимок? В EF Core написание хранимок?

на этапе миграции можно занести хранимку в БД и вызывать в любом удобном месте приложения :)

Всегда начинаю работу с EF отключая все свистелки. Предпочитаю все изменения самому контролировать:

public MainDbContext(DbContextOptions options) : base(options)
{
this.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
this.ChangeTracker.LazyLoadingEnabled = false; //nav prop
this.ChangeTracker.AutoDetectChangesEnabled = false;
}

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории