Как сохранить DbContext в подключенном состоянии с помощью Web API

#c# #entity-framework #asp.net-web-api #asp.net-core #ef-core-2.0

#c# #entity-framework #asp.net-web-api #asp.net-core #ef-core-2.0

Вопрос:

Поскольку веб-API не имеют состояния, когда у вас есть серверная часть EF Core, после любого запроса DbContext будет отключен.

Поэтому мы сделали QueryTracking as NoTracking , поскольку поведение по умолчанию TrackAll не дает никаких преимуществ, поскольку это веб-приложение

 DbContext.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
  

Есть ли способ сохранить DbContext в подключенном состоянии при использовании через веб-API?

Например:

  • Запрос 1: Информация о клиенте извлекается из веб-API
  • Запрос 2: Информация о клиенте сохраняется через другую конечную точку.

Есть ли способ повторно использовать / сохранить подключенное состояние для вышеупомянутого сценария?

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

1. Если под «подключенным состоянием» вы подразумеваете: Сохраняйте изменения, которые были внесены в вашу модель, на протяжении всего выполнения вашего приложения webapi, для меня это не имеет смысла, кроме того, это потребляло бы огромное количество ресурсов (в зависимости от того, как долго вам нужно будет поддерживать работу вашего приложения).

2. Я согласен, но в чем тогда польза от поведения TrackAll по умолчанию? Это полезно только для настольных приложений, но если настольный клиент снова используется многими, цель теряется

3. Не совсем, это означает, что все изменения, которые будут внесены в вашу модель >> во время запроса<<, будут отслеживаться. Таким образом, для всего рабочего процесса запроса вы можете отслеживать или нет изменения в вашей модели, в зависимости от того, что вы хотите сделать … например, для операций чтения можно отключить параметры ‘trackAll’.

4. Зачем вам нужно сохранять DbContext для запроса на ПОЛУЧЕНИЕ и СОХРАНЕНИЕ данных? Я не вижу сценария, в котором это могло бы понадобиться, не могли бы вы немного прояснить это? Тем не менее, вы могли бы создать экземпляр DbContext для каждого пользователя и сохранить его в статическом / сеансе, но опять же, я не вижу никаких причин для этого.

5. @Nipuna Крис Пратт объясняет некоторые заблуждения в этом вопросе. DbContext всегда отключен . DbContexts удаляются как можно быстрее, независимо от того, используете ли вы их в веб- или настольном приложении. Отслеживание не имеет ничего общего с подключениями. Стандартный TrackAll очень полезен в веб-приложениях — как еще вы могли бы загрузить объект на основе идентификатора и изменить одно из его полей?

Ответ №1:

Похоже, вы страдаете от ряда заблуждений / недопонимания. Во-первых, соединения полностью отделены от отслеживания, состояния и всего остального здесь, честно говоря. В частности, если вы используете пул соединений, одно и то же подключение к базе данных вполне может использоваться во многих разных запросах и даже экземплярах контекста. То, что контекст удален, не означает, что соединение с базой данных также закрыто. Аналогично, создание экземпляра контекста не всегда приравнивается к установлению нового соединения.

Во-вторых, отслеживание запросов связано с сохранением кэша объектов EF и отслеживанием изменений, которые он выполняет. Отключение этой функции может иметь некоторые преимущества, поскольку кэш и отслеживание изменений потребляют некоторое количество ресурсов. Однако это также может негативно повлиять на производительность, в зависимости от типа выполняемых вами запросов. В частности, кэш объектов может предотвратить даже необходимость выдачи последующих запросов, если объекты уже были извлечены другими способами. Но, что важно, объектный кэш тесно связан с экземпляром контекста и, следовательно, имеет тот же срок службы, что и сам контекст. Он не сохраняется во всех запросах, которые вы, кажется, понимаете, но он сохраняется во всех операциях, выполняемых в рамках одного конвейера запросов, который вы, похоже, не понимаете. Контекст потенциально может использоваться любое количество раз в течение одного запроса, поэтому отслеживание запросов по-прежнему имеет значение. Вместо того, чтобы полностью отключать его, вы должны выбирать в каждом конкретном случае, когда не использовать его путем добавления .AsNoTracking() к запросу, если это имеет смысл делать в этих конкретных обстоятельствах.

В-третьих, HTTP не имеет состояния, а не только веб-API. Даже традиционные веб-приложения, возвращающие HTML, не имеют состояния. Такие вещи, как Session являются поддельным состоянием. Каждый HTTP-запрос полностью уникален, не зависит ни от чего, что происходило до или после между клиентом и сервером. В случае сеансов, авторизации и т.д. идентификатор передается клиенту с сервера (cookie), и клиент отправляет его обратно на сервер с каждым последующим запросом. Это создает иллюзию состояния, но на самом деле оно каждый раз устанавливается заново.

Таким образом, нет способа сохранить результаты запроса между запросами, за исключением использования чего-то вроде Session или кэша. Даже тогда результат для ваших целей здесь не сработал бы, поскольку данные должны были бы быть сериализованы / десериализованы, удаляя любые связи с каким-либо отслеживанием состояния, т. Е. Это просто данные, и EF, например, ничего не знал бы об этом или о том, как сохранить изменения в нем.