Добавил:
Преподаватель Колледжа информационных технологий Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Лекции / Глава 17.1 Entity Framework

.pdf
Скачиваний:
44
Добавлен:
08.05.2022
Размер:
625.06 Кб
Скачать

ОСНОВНЫЕ ОПЕРАЦИИ С ДАННЫМИ

Большинство операций с данными представляют собой CRUD-

операции (Create, Read, Update, Delete), то есть получение данных, создание,

обновление и удаление. Entity Framework позволяет легко производить данные операции.

Для примеров с операциями возьмем модель User, созданную в предыдущем параграфе:

Листинг 17.7

1

public partial class User

 

2

{

 

3

public int Id { get; set; }

 

4

public string Log { get; set; }

 

5

public string Password { get; set; }

 

6

}

 

 

И следующий класс контекста данных:

 

Листинг 17.8

 

 

 

1

public partial class UserContainer : DbContext

 

2

{

 

3

public UserContainer() : base("name=UserContainer")

 

{}

 

 

 

4

protected override void

 

OnModelCreating(DbModelBuilder modelBuilder)

 

 

 

5

{

 

6

throw new UnintentionalCodeFirstException();

 

7

}

 

8

public virtual DbSet<User> Users { get; set; }

 

9

}

 

 

Добавление (CREATE)

Создадим форму добавления новых объектов:

Рисунок 1

 

Для добавления применяется метод Add() у объекта DbSet:

 

Листинг 17.9

 

 

 

1

using (UserContainer db = new UserContainer())

 

2

{

 

3

User user = new User() { Log = textBoxLog.Text,

 

Password = textBoxPassword.Text };

 

 

 

4

db.Users.Add(user);

 

5

db.SaveChanges();

 

6

}

 

7

listBoxUsers.Items.Clear();

 

8

using (UserContainer db = new UserContainer())

 

9

{

 

10

foreach (var item in db.Users)

 

11

{

 

12

listBoxUsers.Items.Add(item.Log);

 

13

}

 

14

}

 

После добавления надо сохранить все изменения с помощью метода

SaveChanges(). В строках 7-13 происходит обновление списка – в него загружаются все элементы из таблицы Users.

Рисунок 2

Обновление (UPDATE)

Создадим форму редактирования объектов, хранящихся в таблице

Users:

Рисунок 3

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

 

Листинг 17.10

 

 

 

1

User user = null;

 

 

 

 

2

using (UserContainer db = new UserContainer())

 

 

 

 

3

{

 

 

 

 

4

foreach (var item in db.Users)

 

 

 

 

5

{

 

 

 

 

6

if (item.Log == (string)listBoxUsers.SelectedItem)

 

 

 

 

7

{

 

 

 

 

8

user = db.Users.Find(item.Id);

 

 

 

 

9

}

 

 

 

 

10

}

 

 

 

 

11

user.Log = textBoxNewLog.Text;

 

 

 

 

12

user.Password = textBoxNewPassword.Text;

 

 

 

 

13

db.SaveChanges();

 

 

 

 

14

}

 

Здесь user – объект, который выбирается из списка listBoxUsers для дальнейшего редактирования.

Для поиска искомого объекта в базе данных используется метод Find

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

Рассмотрим ситуацию, где объект User будет получен в одном контексте, а изменять свои значения будет для другого контекста, который его не отслеживает:

 

Листинг 17.11

 

 

 

1

User user = null;

 

2

using (UserContainer db = new UserContainer())

 

3

{

 

4

foreach (var item in db.Users)

 

5

{

 

6

if (item.Log == (string)listBoxUsers.SelectedItem)

 

7

{

 

8

user = db.Users.Find(item.Id);

 

9

}

 

10

}

 

11

}

 

12

using (UserContainer db = new UserContainer())

 

13

{

 

14

user.Log = textBoxNewLog.Text;

 

15

user.Password = textBoxNewPassword.Text;

 

16

db.SaveChanges();

 

17

}

 

 

В итоге при попытке обновления изменения не сохранятся. Чтобы

изменения сохранились, нам явным образом надо установить для состояния объекта значение EntityState.Modified:

 

Листинг 17.12

 

 

 

1

using (UserContainer db = new UserContainer())

 

2

{

 

3

user.Log = textBoxNewLog.Text;

 

4

user.Password = textBoxNewPassword.Text;

 

5

db.Entry(user).State = EntityState.Modified;

 

6

db.SaveChanges();

 

7

}

 

 

Метод Entry получает объект DbEntityEntry для данной сущности из

контекста UserContainer, предоставляющий доступ к информации о сущности и возможность выполнять действия с этой сущностью. В нашем случае с помощью свойства State изменяется состояние измененной

сущности для возможности присоединения ее к контексту и дальнейшей ее отправки в базу данных при вызове метода SaveChanges.

Удаление (DELETE)

Создадим форму удаления объектов, хранящихся в таблице Users:

 

Рисунок 4

 

Для удаления объекта применяется метод Remove() объекта DbSet:

 

Листинг 17.13

 

 

 

1

User user = null;

 

2

using (UserContainer db = new UserContainer())

 

3

{

 

4

foreach (var item in db.Users)

 

5

{

 

6

if (item.Log == (string)listBoxUsers.SelectedItem)

 

7

{

 

8

user = db.Users.Find(item.Id);

 

9

}

 

10

}

 

11

db.Users.Remove(user);

 

12

db.SaveChanges();

 

13

}

 

Метод Remove помечает сущность, переданную в параметры, как удаленную, так что она будет удалена из базы данных при вызове

SaveChanges. Обратите внимание, что перед вызовом этого метода объект должен существовать в контексте в каком-то другом состоянии.

Но, как и в случае с обновлением здесь мы можем столкнуться с похожей проблемой, когда объект получаем из базы данных в пределах одного контекста, а пытаемся удалить в другом контексте. И в этом случае нам надо установить вручную у объекта состояние EntityState.Deleted:

 

Листинг 17.14

 

 

 

1

using(UserContainer db = new UserContainer())

 

2

{

 

3

db.Entry(user).State = EntityState.Deleted;

 

4

db.SaveChanges();

 

5

}

 

В данном случае состояние сущности изменяется на “Удалено” для ее удаления из базы данных и отсоединения из контекста после вызова метода

SaveChanges.

Присоединение существующей сущности к контексту

Если у вас есть сущность, которая уже существует в базе данных, но в настоящий момент не отслеживается контекстом, можно указать контексту отслеживание сущности с помощью метода Attach в DbSet. Сущность будет находиться в неизмененном состоянии в контексте.

Например:

Листинг 17.15

1

User user = new User() { Log = textBoxLog.Text, Password =

textBoxPassword.Text };

2

using (UserContainer db = new UserContainer())

3

{

4

db.Users.Attach(user);

5

string tempLog = db.Entry(user).Entity.Log;

6

db.Entry(user).Entity.Log = "Пользователь ";

7

db.Entry(user).Entity.Log += tempLog;

8

db.Users.Add(db.Entry(user).Entity);

9

db.SaveChanges();

10}

Встроке 4 объект user помещается в контекст данных UserContainer

внеизмененном состоянии. Далее, в строке 5 в строковую переменную

tempLog сохраняется логин, полученный от объекта, который был ранее помещен в контекст. В строках 6-7 происходит изменение структуры логина – в начало помещается слово “Пользователь”, после которого идет старый логин, записанный в поле ввода при создании пользователя. После этого, в

строке 8, происходит добавление объекта в контекст для дальнейшего добавления в базу данных после вызова метода SaveChanges.

Обратите внимание, что в базу данных не вносятся изменения, если метод SaveChanges вызывается без выполнения других манипуляций с присоединенной сущностью. Это вызвано тем, что сущность находится в

неизмененном состоянии.