Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этом разделе описано, как добавлять и присоединять сущности к контексту и как Entity Framework обрабатывает эти сущности во время SaveChanges. Entity Framework заботится об отслеживании состояния сущностей, пока они подключены к контексту, но в отключённых или N-уровневых сценариях вы можете указать EF, в каком состоянии должны находиться ваши сущности. Методы, показанные в этом разделе, применяются одинаково к моделям, созданным с помощью code First и ef Designer.
Состояния сущностей и SaveChanges
Сущность может находиться в одном из пяти состояний, определенных перечислением EntityState. Ниже перечислены следующие состояния:
- Добавлено: сущность отслеживается контекстом, но еще не существует в базе данных
- Без изменений: сущность отслеживается контекстом и существует в базе данных, а ее значения свойств не изменились с значений в базе данных.
- Изменено: сущность отслеживается контекстом и существует в базе данных, а некоторые или все его значения свойств были изменены.
- Удалено: сущность отслеживается контекстом и существует в базе данных, но помечена для удаления из базы данных при следующем вызове SaveChanges
- Отсоединенный: сущность не отслеживается контекстом
SaveChanges выполняет различные действия для сущностей в разных состояниях:
- Неизмененные сущности не затрагиваются SaveChanges. Обновления не отправляются в базу данных для сущностей в неизменном состоянии.
- Добавленные сущности вставляются в базу данных, а затем становятся неизменными при возврате SaveChanges.
- Измененные сущности обновляются в базе данных, а затем становятся неизменными при возврате SaveChanges.
- Удаленные сущности удаляются из базы данных и затем отсоединяются от контекста.
В следующих примерах показаны способы изменения состояния сущности или графа сущностей.
Добавление новой сущности в контекст
Новую сущность можно добавить в контекст, вызвав метод Add в DbSet. При этом сущность помещается в состояние "Добавлено", то есть она будет вставлена в базу данных при следующем вызове SaveChanges. Рассмотрим пример.
using (var context = new BloggingContext())
{
var blog = new Blog { Name = "ADO.NET Blog" };
context.Blogs.Add(blog);
context.SaveChanges();
}
Другим способом добавления новой сущности в контекст является изменение его состояния на Added. Рассмотрим пример.
using (var context = new BloggingContext())
{
var blog = new Blog { Name = "ADO.NET Blog" };
context.Entry(blog).State = EntityState.Added;
context.SaveChanges();
}
Наконец, можно добавить новую сущность в контекст, подключив ее к другой сущности, которая уже отслеживается. Это может быть сделано добавлением новой сущности в свойство навигации коллекции одной сущности или заданием свойства навигации ссылки другой сущности таким образом, чтобы оно указывало на новую сущность. Рассмотрим пример.
using (var context = new BloggingContext())
{
// Add a new User by setting a reference from a tracked Blog
var blog = context.Blogs.Find(1);
blog.Owner = new User { UserName = "johndoe1987" };
// Add a new Post by adding to the collection of a tracked Blog
blog.Posts.Add(new Post { Name = "How to Add Entities" });
context.SaveChanges();
}
Обратите внимание, что для всех этих примеров, если добавленная сущность содержит ссылки на другие сущности, которые еще не отслеживаются, эти новые сущности также будут добавлены в контекст и будут вставлены в базу данных при следующем вызове SaveChanges.
Присоединение существующей сущности к контексту
Если у вас уже есть сущность, которая уже существует в базе данных, но которая в настоящее время не отслеживается контекстом, можно определить контекст для отслеживания сущности с помощью метода Attach в DbSet. Сущность будет находиться в неизменном состоянии в контексте. Рассмотрим пример.
var existingBlog = new Blog { BlogId = 1, Name = "ADO.NET Blog" };
using (var context = new BloggingContext())
{
context.Blogs.Attach(existingBlog);
// Do some more work...
context.SaveChanges();
}
Обратите внимание, что никакие изменения не будут вноситься в базу данных, если saveChanges вызывается без каких-либо других операций с присоединенной сущностью. Это связано с тем, что сущность находится в состоянии "Без изменений".
Другим способом подключения существующей сущности к контексту является изменение состояния на "Без изменений". Рассмотрим пример.
var existingBlog = new Blog { BlogId = 1, Name = "ADO.NET Blog" };
using (var context = new BloggingContext())
{
context.Entry(existingBlog).State = EntityState.Unchanged;
// Do some more work...
context.SaveChanges();
}
Обратите внимание, что для обоих этих примеров, если присоединенная сущность имеет ссылки на другие сущности, которые еще не отслеживаются, эти новые сущности также будут присоединены к контексту в без изменений состоянии.
Присоединение существующей, но измененной сущности к контексту
Если у вас есть сущность, которая уже существует в базе данных и к которой могли быть внесены изменения, вы можете сообщить контексту присоединить сущность и установить ее состояние как "Изменено". Рассмотрим пример.
var existingBlog = new Blog { BlogId = 1, Name = "ADO.NET Blog" };
using (var context = new BloggingContext())
{
context.Entry(existingBlog).State = EntityState.Modified;
// Do some more work...
context.SaveChanges();
}
При изменении состояния на "Изменить" все свойства сущности будут помечены как измененные, и все значения свойств будут отправлены в базу данных при вызове SaveChanges.
Обратите внимание, что если присоединенная сущность содержит ссылки на другие сущности, которые еще не отслеживаются, эти новые сущности будут присоединены к контексту в состоянии 'Без изменений' — они не будут переведены в состояние 'Изменено' автоматически. Если у вас есть несколько сущностей, которые необходимо пометить "Изменить", необходимо задать состояние для каждой из этих сущностей по отдельности.
Изменение состояния отслеживаемой сущности
Вы можете изменить состояние сущности, которая уже отслеживается, установив свойство State в ее записи. Рассмотрим пример.
var existingBlog = new Blog { BlogId = 1, Name = "ADO.NET Blog" };
using (var context = new BloggingContext())
{
context.Blogs.Attach(existingBlog);
context.Entry(existingBlog).State = EntityState.Unchanged;
// Do some more work...
context.SaveChanges();
}
Обратите внимание, что для изменения состояния сущности можно также использовать вызов "Добавить или подключить" для уже отслеживаемой сущности. Например, вызов функции Attach для сущности, которая в настоящее время находится в состоянии "Добавлено", изменит её состояние на "Без изменений".
Вставка или обновление шаблона
Распространенный шаблон для некоторых приложений заключается в добавлении сущности в качестве новой (в результате вставки базы данных) или присоединению сущности как существующей и помечать ее как измененную (в результате обновления базы данных) в зависимости от значения первичного ключа. Например, при использовании созданных в базе данных первичных ключей целочисленного числа обычно рассматривается сущность с нулевым ключом как новой и сущностью с ненулевым ключом как существующей. Этот шаблон можно достичь, задав состояние сущности на основе проверки значения первичного ключа. Рассмотрим пример.
public void InsertOrUpdate(Blog blog)
{
using (var context = new BloggingContext())
{
context.Entry(blog).State = blog.BlogId == 0 ?
EntityState.Added :
EntityState.Modified;
context.SaveChanges();
}
}
Обратите внимание, что при изменении состояния на "Изменить" все свойства сущности будут помечены как измененные, а все значения свойств будут отправляться в базу данных при вызове SaveChanges.