Entity framework добавление данных в базу данных

Обновлено: 07.07.2024


ChangeTracker и состояние объекта в Entity Framework Core

Прежде чем мы начнем изменять данные с помощью Entity Framework Core, мы должны ознакомиться с некоторыми дополнительными функциями EF Core.

Как мы узнали, в первой части серии, DbContext состоит всего из трех свойств: ChangeTracker , Database и Model . Мы видели свойства модели и базы данных в действии в предыдущих статьях, поэтому в этой статье мы поговорим о свойствах ChangeTracker и State .

Свойство ChangeTracker обеспечивает доступ к информации отслеживания изменений и операциям с загруженной в данный момент сущностью. Эта возможность очень важна, когда мы хотим выполнить любую операцию модификации базы данных. EF Core имеет такую ​​информацию (об отслеживании и операциях) независимо от того, создаем ли мы ее, изменяем или удаляем сущность.

Кроме того, EF Core не будет выполнять никаких операций, пока мы не вызовем метод SaveChanges . Поэтому знание того, какую операцию мы хотим выполнить, имеет решающее значение для EF Core до вызова метода SaveChanges .

Каждой отслеживаемой сущности присвоено свойство State. Когда мы используем объект контекста для загрузки сущности без метода AsNoTracking или меняем ее состояние с помощью методов Update, Remove или Add, эта сущность будет отслеживаемой сущностью. Значение свойства State можно получить с помощью команды _context.Entry(our_entity).State .

Вот возможные состояния отслеживаемых объектов:

  • Detached - объект не отслеживается, и вызов метода SaveChanges не даст никакого эффекта.
  • Unchanged - объект загружен из базы данных, но не имеет изменений. Метод SaveChanges игнорирует его.
  • Added - объект не существует в базе данных, и вызов метода SaveChanges добавит его в базу данных.
  • Modified - объект существует в базе данных и был изменен, поэтому вызов метода SaveChanges изменит его в базе данных.
  • Deleted - объект существует в базе данных, и как только мы вызовем метод SaveChanges, он будет удален из базы данных.

Теперь, когда мы все это знаем, мы можем перейти к операциям Create , Update и Delete .

Добавление данных с помощью методов Add и AddRange

Мы можем создавать новые строки в базе данных с помощью методов Add и AddRange. Метод Add изменяет состояние отдельной сущности, где AddRange может делать то же самое, но для нескольких сущностей. Давайте посмотрим, как работает метод Add после того, как мы отправим объект student из Postman:

После этих проверок мы вызываем метод Add , чтобы изменить состояние объекта на «Добавлено», и вызываем метод SaveChanges для создания новой строки в базе данных. Последняя строка кода вернет созданную сущность (с ее идентификатором) клиенту:


Это результат в базе данных:


Отслеживание изменений при добавлении объекта

Если мы немного изменим наш код, мы сможем проверить, как изменяется состояние объекта во время этого действия. Конечно, для сохранения объекта в базе данных дополнительный код не требуется, он здесь только в учебных целях:


Как мы видим, перед добавлением нашей сущности в базу данных она находится в состоянии Detached . Как только мы используем метод Add , он принимает состояние Added . Наконец, после метода SaveChanges он имеет состояние Unchanges .

Использование метода AddRange

Когда мы хотим добавить несколько строк в базу данных, мы используем метод AddRange . Это та же процедура, только другой метод:

Еще одна важная вещь, о которой следует упомянуть, заключается в том, что метод SaveChanges выполняет требуемую операцию, но также возвращает количество затронутых строк. Поэтому, если нам нужно проверить, сколько строк затронуто нашей операцией, мы всегда можем вернуть результат метода SaveChanges:

Добавление связанных объектов в базу данных

Теперь мы собираемся узнать, как включать отношения при добавлении основной сущности в базу данных. Чтобы продемонстрировать это, мы собираемся немного изменить наш первый пример:

Как видно из приведенного выше кода, мы только добавляем объект student к объекту контекста приложения, но объект studentDetails также добавляется в базу данных:


И мы можем проверить ответ от приложения:


Важно отметить, что мы не добавляем значение Id вручную для какой-либо сущности, за это отвечает EF Core. В базе данных видно, что значения GUID были созданы.

Отлично. То же самое можно сделать с отношениями "один ко многим" или "многие ко многим".

Обновление строк в базе данных

Есть два способа обновить строки в базе данных. С подключенным обновлением и с отключенным обновлением. Разница в том, что с подключенным обновлением мы используем один и тот же объект контекста для загрузки и изменения сущности. При отключенном обновлении дело обстоит иначе. Либо мы используем разные объекты контекста, либо получаем объект от клиента, который имеет все свойства как сущность в базе данных, поэтому мы можем обновить его без предварительной загрузки действия.

При работе с подключенным обновлением необходимо выполнить три основных шага:

  • Чтение данных из базы данных (с ее связями или без них).
  • Изменить одно или несколько свойств.
  • Вызов метода SaveChanges.

Итак, давайте посмотрим на связанное обновление в действии, когда мы отправим объект student от клиента с обновленным свойством Name :

Мы видим все три шага в приведенном выше коде. Мы загружаем объект студента на основе его идентификатора, затем сопоставляем свойства из обновленного студента клиента, который устанавливает состояние объекта на Modified и, наконец, мы вызываем SaveChanges . Несмотря на то, что мы изменили только свойство Name , мы должны сопоставить все свойства, потому что мы не знаем, что именно было изменено на стороне клиента.

EF Core, с другой стороны, содержит информацию о том, что именно было изменено.

Когда мы загружаем нашу сущность, EF Core начинает отслеживать ее, и в этот момент состояние становится Unchanged . Как только мы изменяем какое-либо свойство загруженного объекта, оно изменяет State на Modified . Наконец, после метода SaveChanges состояние возвращается к Unchanges .

Как только мы отправим запрос на это действие PUT, имя учащегося будет обновлено:


Мы видим, что обновлено только свойство Name. Если вы не видите обе команды в окне консоли, вы наверняка можете найти их в окне вывода в Visual Studio.

Свойство IsModified

Когда у нас есть сущность, которая уже находится в состоянии Modified , EF Core использует другое свойство, которое предоставляет информацию о том, что действительно изменилось. Это свойство IsModified , и мы можем изучить, как оно работает, немного изменив наш код:


Результат здесь не требует пояснений.

Обновление отношений в EF Core

Добавить отношения к операциям обновления в EF Core довольно просто. Мы можем прикрепить реляционную сущность к основной сущности, изменить ее, а все остальное EF Core сделает за нас, как только мы вызовем метод SaveChanges . Процедура такая же, как и для действий create.

Когда мы отправляем нашу форму запроса Postman, мы собираемся обновить сущность student и сущность studentDetails :


Тот же процесс применяется к другим типам отношений.

Важно знать, что когда мы обновляем нашу основную сущность, добавляя новую сущность отношения, EF Core создаст новую строку в таблице отношений и соединит ее с основной сущностью с помощью внешнего ключа:


Поскольку теперь мы знаем, как обновлять отношения в EF Core, мы можем перейти к отключенному обновлению.

Неотслеживаемое обновление в EF Core

Есть несколько способов выполнить неотслеживаемое обновление, и мы собираемся показать вам два способа сделать это. В первом примере мы собираемся прикрепить объект, отправленный от клиента, изменить его состояние, а затем сохранить его в базе данных:

Объект student , отправленный от клиента, имеет в начале состояние Detached . После того, как мы воспользуемся методом Attach , объект изменит состояние на Unchanged .

Это также означает, что с этого момента EF Core начинает отслеживать объект. Теперь мы собираемся изменить состояние на Modified и сохранить его в базе данных.

Это объект, отправленный клиентом:

Как видите, у него также есть свойство Id . Кроме того, мы изменили свойства Name и IsRegularStudent , но EF Core обновит весь объект в базе данных.

Другой способ сделать то же самое - использовать метод Update или UpdateRange , если у нас есть несколько объектов, готовых к обновлению. Итак, давайте отправим тот же объект только с измененным свойством IsRegularStudent на true:

Мы видим разницу. Метод Update установит отслеживаемую сущность, а также изменит ее состояние с Detached на Modified . Таким образом, нам не нужно прикреплять сущность и явно изменять ее состояние, потому что это делает за нас метод Update . Этот подход также обновит весь объект, даже если мы изменили только одно свойство:


Теперь мы знаем, как выполнить отключенное обновление и в чем отличие от подключенного обновления.

Операция удаления в EF Core

У нас есть два способа удаления строк, и мы рассмотрим их оба.

Soft Delete в Entity Framework Core

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

По сути, мы не удаляем объект, мы обновляем его, изменяя его свойство (мы собираемся назвать его "Удаленным") на true.

Чтобы показать, как работает мягкое удаление, нам нужно внести некоторые изменения в нашу текущую модель базы данных. Для начала изменим модель Student , добавив дополнительное свойство:

Теперь давайте изменим класс StudentConfiguration , добавив дополнительный метод для фильтрации всех удаленных учащихся из запросов:

Метод HasQueryFilter будет включать только те сущности Student , для свойства Deleted которых установлено значение false. Или, другими словами, он проигнорирует всех учащихся, для которых для параметра Deleted установлено значение true.

Чтобы применить эти изменения к базе данных, мы собираемся создать и применить миграцию:

После этого переноса для всех строк в таблице Student столбец Deleted будет иметь нулевое значение (false).

Чтобы продолжить, давайте создадим дополнительное действие "Удалить" в контроллере и отправим запрос на удаление:

Мягкое удаление состоит из трех этапов:

  • Загрузка
  • Редактирование
  • Удаление

Это результат в базе данных:


Загрузка данных с использованием QueryFilter и игнорирование QueryFilter

С помощью метода HasQueryFilter мы убедились, что «удаленные» объекты не будут включены в результат запроса. Посмотрим, работает ли это:

EF Core обычно возвращает всех студентов из таблицы Student. Но с реализованным методом HasQueryFilter результат другой:


Мы можем подтвердить, что «Student updated 3» отсутствует, поскольку это единственное свойство, у которого для свойства Deleted установлено значение true.

Конечно, если мы хотим игнорировать наш фильтр запроса, мы можем сделать это, применив к запросу IgnoreQueryFilter :

Этот запрос будет включать «удаленную» сущность:


Отличная работа. Давайте продолжим обычное удаление.

Удаление отдельной сущности с помощью EF Core

При обычном удалении мы не изменяем нашу сущность, а фактически удаляем ее из базы данных с помощью метода Remove или RemoveRange для нескольких сущностей:

Это действие также выполняется в три этапа:

  • Загрузка объекта "Student" и установка его состояния на "Без изменений".
  • Использование метода Remove для установки состояния "Удалено".
  • Сохранение изменений в базе данных

Мы должны быть осторожны с действиями удаления, если у нашей сущности есть связи, и мы не указали их в действии удаления. Удаление основного объекта может привести к удалению и взаимосвязей (каскадное удаление), в зависимости от конфигурации объекта.

Это переведенная команда SQL:


Мы видим, что первая инструкция Select включает фильтр запроса. Сразу после фильтра идет наш запрос на удаление.

Удаление объекта вместе со связанными данными

Чтобы удалить объект с его отношениями, все, что нам нужно сделать, это включить эту связь в основную сущность:

И это все, что нам нужно сделать. Остальное EF Core сделает за нас.

Заключение

Мы надеемся, что вам понравилось это читать и вы нашли много полезной информации.

Работа с данными в Entity Framework

Всем доброго времени суток. На связи Алексей Гулынин. В прошлых статьях мы рассмотрели различные подходы по работе с Entity Framework. В данной статье я бы хотел рассказать, как работать с данными в Entity Framework. Рассмотрим следующие операции:

  1. Добавление записи
  2. Чтение записей
  3. Редактирование записи
  4. Удаление записи

Создадим новый проект. В этот раз тип проекта будет "Приложение Windows Forms":

Добавим элемент DataGridView на нашу форму. Также добавим 3 кнопки: "Добавление", "Редактирование", "Удаление". Добавим ещё 2 элемента "TextBox", в которые будем выводить информацию о записи, которая в данный момент выделена (эти 2 "TextBox" будут использованы ещё для добавления новой записи). Добавим ещё один "TextBox", в который будет выводиться информация об "ID" записи (это нужно будет для редактирования записи). Также добавим 2 элемента "label". В конечном итоге наша форма будет выглядеть следующим образом:

Работа с данными в EF

Будем использовать подход "Code First". Создадим следующий класс:

Основной код будет в файле "Form1.cs". Сразу приведу весь код, в комментариях он будет подробно рассмотрен:

Работа с данными в EF

В данной статье вы узнали, как просто работать с данными в Entity Framework.

На связи был Алексей Гулынин, оставляйте свои комментарии, увидимся в следующих статьях.

Проблема с добавление данных в БД с ипользованием Entity Framework, никак не могу понять причину, почему после добавления в БД записи с неуникальным ключом, все последующие записи отбрасываются с ошибкой.

Т.е. после ошибки (исключение "System.Data.Entity.Infrastructure.DbUpdateException" в EntityFramework.dll):

Вставить корректную запись не удается (исключение "System.Data.Entity.Infrastructure.DbUpdateException" в EntityFramework.dll), хотя строка имеет уже уникальные значения ключа:

Контекст создается в конструкторе: public class Class_EntityConnection

Метод добавления в БД заполненного класса:

Метод создания и заполнения класса и передача его на запись:

Лог успешной транзакции:

Лог ошибочной (специально введены некорректные значения ключа)

Последующие транзакции в сеансе выдают аналогичный лог.


Распространенной практикой является создание контекста при каждом обращении к БД, в блоке using . В результате после выхода из блока все коллекции с сущностями уничтожаются. Другой частой практикой является использование автогенерируемого в БД ключа. То есть на клиенте его не нужно задавать. Если это позволяет ваша модель данных, то рассмотрите переход на этот способ. Тут советуют проверять уникальность ключа перед вставкой. Погуглил - тоже сплошь и рядом это советуют. Волосы дыбом встают от таких советов, если честно. Это ж лишний запрос в БД (раунд-трип может быть очень дорог по времени), это лишняя нагрузка на сеть и СУБД. А главное - это не даёт никаких гарантий: сделали запрос, убедились, что ключ уникален (тут от другого клиента пришёл запрос на вставку, успешно завершился), сделали свой запрос на вставку - внезапно, словили исключение - наш ключ совпал с только что вставленным другим клиентом. Db.Entry(entity).State = EntityState.Added; - если после SaveChanges() вылетает ошибка про дубликат, то данную entity надо удалить из контекста что бы при следующем сохранении не словить туже ошибку, или же изменить ключ на уникальный у экземпляра entity Всем - есть желающие подробно ответить на поставленные вопросы? На удивление, на английском so тоже нет ничего подходящего. Я назначу конкурс, как станет возможно, так что готовьтесь. Что хотелось бы видеть в ответе: необходимость удаления сущности из контекста, после выброса исключения; достоинства-недостатки локального/глобального контекста; автогенерируемый в БД ключ (и как его получать потом в EF); плюсы-минусы предварительной проверки уникальности ключей.

Дело в том, что DbContext реализует паттерн Unit of Work (Единица Работы). Паттерн используется для представления бизнес-транзакций на уровне предметной области.

Единица работы копит изменения, которые должны быть сделаны в базе данных и затем сохраняет их все вместе. В DbContext для регистрации добавления/удаления применяют методы DbSet.Add и DbSet.Delete , а для сохранения — метод SaveChanges .

Здесь и кроется корень проблемы. Если при сохранении возникает исключение, все объекты помеченные на вставку, обновление или удаление, таковыми и остаются. При следующем сохранении DbContext попробует снова сохранить их в базе данных.

Вставлять запись лучше через метод Add :

В вашем случае DbContext надо создавать для каждой записи. Но есть и другие способы. Если записей не очень много, в пределах нескольких сотен, вы можете прочитать их в память, и уже в памяти определить, какие их них новые, а какие существующие. Если записей много, ту же самую операцию можно сделать постраничной.

Поздняя вставка В комментариях написали, что эта схема будет работать только если вставка выполняется с одного клиента, а несколько клиентов будут друг другу мешать. Это верно. К сожалению, эта задача плохо решается даже не на уровне Entity Framework, а на уровне непосредственно БД. Даже если писать на чистом SQL, вставка/изменение большого количества записей с разных клиентов будет выполняться строго последовательно (как пишет Фаулер, в этом случае применяется паттерн Пессимистическая блокировка).

Такие задачи решают не техническими, а организационными средствами. В моей практике был такой опыт, и там вставкой/обновлением занимался единственный клиент, фоновый процесс, который запускался несколько раз в день. Все остальные клиенты (рабочие места операторов) большую часть данных только читали, поэтому и проблем с блокировками было гораздо меньше. Конец вставки

Можно также в явном виде вызывать SQL-запрос, который на сленге программистов называется UPSERT. Если запись уже есть, то это будет UPDATE, а если её нет, то INSERT.

Для SQL Server запрос UPSERT делается с помощью команды MERGE .

EF напрямую не поддерживает инструкцию MERGE , но он позволяет выполнять SQL-запросы. В новом EF Core это может быть сделано так:

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

Вторым недостатком является не очень высокая скорость внесения изменений. Чтобы ускорить, можно сделать групповую вставку во временную таблицу и затем вставлять/обновлять данные уже из неё.

Плюсом будет то, что такой метод исключает конфликт идентификаторов, даже если вставка происходит с разных клиентов, и при этом не сильно блокирует систему.

Здравствуйте, подскажите, как добавлять данные в таблицы с помощью EF?

Например, есть таблицы:
Regions: id, region, population
Districts: id, district, population, region_id
Cities: id, city, population, district_id

Связь 1 ко многим

__________________
Помощь в написании контрольных, курсовых и дипломных работ здесь

Entity framework показ данных по частям
Допустим в таблице содержится большое количество записей(около миллиона) как можно частями выбирать.


Добавление данных в таблицу. Entity framework
Здравствуйте, не могу добавить новую запись в базу данных с помощью EF. Form1 main = this.Owner as.

Entity Framework. Добавление данных в базу из текстового файла
Имеем кнопку, при нажатии на которую таблица должна заполняться из текстового файла: protected.

Entity Framework Database-First добавление данных. Не инкрементируется primary key
Здравствуйте, форумчане. Разбираюсь с добавлением данных в EF. Суть проблемы такая: при вставке.

Здравствуйте, подскажите, как добавлять данные в таблицы с помощью EF?

Usaga, читала, если добавление такое сделать для таблицы regions, то все в порядке, но добавление в таблицу districts уже не работает. Пишет ошибку.

И добавления в таблицу regions после каждого запуска программы перезаписывается, не сохраняются раннее добавленные данные

Какую? Это нам надо угадать?)

Значит файл базы перезаписываете при сборке приложения.

Usaga, а как сделать, чтобы не перезаписывался ?

Добавлено через 2 минуты
Usaga, сейчас сброшу ошибку и свои попытки

В свойствах файла базы данных в проекте указать "do not copy". ошибка:
SqlException: The INSERT statement conflicted with the FOREIGN KEY constraint "FK_add". The conflict occurred in database "..\DESKTOP\TEST\BIN\DEBUG\DB.MDF", table "dbo.DB", column 'id'.
The statement has been terminated.

ElKros, ошибка говорит о том, что вы пытаетесь нарушить ограничение внешнего ключа. Которое, судя по всему, повешено на колонку ID (o_O).

Ну и что это за дичь вообще?

ElKros, ID сама база генерировать умеет. Изучать работу с базами надо начиная с SQL, а не с EF'а

Привязка данных из таблицы в ComboBox (Entity Framework)
Здравствуйте. Ситуация, вроде бы, простая: есть таблица, хранящая внешний ключ на другую.

Entity framework - как выводятся таблицы из базы данных посредством DataGridView?
В общем у меня есть база данных sql, подключенная к студии с помощью EF, на форме выводятся таблицы.

Добавление в Entity Framework
Гуглил, но не особо понял , что нужно , чтобы пофиксить это Выборка нормально, а если добавлять и.

Добавление в БД Entity Framework 6
Не добавляет в бд записи, но выводит в консоли единожды после перезапуска приложения вывод прежний.

Entity Framework - добавление друзей
Приветствую! Изучаю Entity Framework Code First. Имеется следующая задача: Есть модель User. .

Читайте также: