Материал: Глава 17.2 Entity Framework

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

3

var FirstProfessor = db.Professors.FirstOrDefault();

4

db.Entry(FirstProfessor).Collection("Theses").Load();

5

foreach (Thesis t in FirstProfessor.Theses)

6

{

7

listBox1.Items.Add(t.Name);

8

}

9

}

В данной программе метод FirstOrDefault находит первый элемент из коллекции Professors и присваивает переменной FirstProfessor.

Далее идет загрузка данных через обращение к методу db.Entry(), в который передается нужный объект. Для подгрузки связанного объекта, который представляет коллекцию, используется метод Collection(). В этот метод передается навигационное свойство в виде строки, по которому надо подгрузить данные.

Если связанные объект не представляет коллекцию, то применяется метод Reference(), в который также передается навигационное свойство.

Ленивая загрузка

Еще один способ представляет так называемая «ленивая загрузка» или lazy loading. При таком способе подгрузки при первом обращении к объекту,

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

При использовании ленивой загрузки надо учитывать некоторые ограничении при описании классов. Так, классы, использующие ленивую загрузку должны быть публичными, а их свойства должны иметь модификаторы public и virtual. Например, классы Professor и Thesis

могут иметь следующее определение:

Листинг 17.22

1public class Professor

2{

3public int Id { get; set; }

4public string Name { get; set; }

5public string Position { get; set; }

6

6

public string PersonalData { get; set; }

7

public virtual ICollection<Thesis> Theses { get; set; }

8

public Professor()

9

{

10

this.Theses = new List<Thesis>();

11

}

12

}

13

public class Thesis

14

{

15

public int Id { get; set; }

16

public string Name { get; set; }

17

public int? ProfessorId { get; set; }

18

public virtual Professor Professor { get; set; }

19}

Вэтом случае нам не потребуется использовать какие-то

дополнительные методы, как Include или Load:

 

Листинг 17.23

 

 

 

1

if (this.Professor.Theses.Count != 0)

 

2

{

 

3

for (int i = 0; i < this.Professor.Theses.Count; i++)

 

4

{

 

5

listBox1.Items.Add(this.Professor.Theses.ToList()[i].Name);

 

6

}

 

7

}

 

 

В данной программе происходит добавление в список listBox1

наименований тем дипломных проектов Professor.Theses.ToList()[i].Name,

закрепленных за преподавателем Professor.

7

§17.9 Связь один к одному

Строго говоря в Entity Framework нет как таковой связи один-к-одному,

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

Но все же нередко возникает потребность в наличие подобной связи между объектами в приложении, и в Entity Framework мы можем настроить данный тип отношений.

Рассмотрим стандартный пример подобных отношений: есть класс пользователя User, который хранит логин, пароль и роль, то есть данные учетных записей. А все данные профиля, такие как имя, номер группы (для студента), должность (для дипломного руководителя) и так далее, выделяются в класс профиля UserProfile.

 

Листинг 17.24

 

 

 

1

using System.Collections.Generic;

 

2

using System.ComponentModel.DataAnnotations;

 

3

using System.ComponentModel.DataAnnotations.Schema;

 

4

…

 

5

public class User

 

6

{

 

7

public int Id { get; set; }

 

8

public string Login { get; set; }

 

9

public string Password { get; set; }

 

10

public string Role { get; set; }

 

11

public UserProfile Profile { get; set; }

 

12

}

 

13

public class UserProfile

 

14

{

 

15

[Key]

 

16

[ForeignKey("User")]

 

17

public int Id { get; set; }

 

18

public string Name { get; set; }

 

19

public int NumberGroup { get; set; }

 

20

public string PersonalDate { get; set; }

 

21

public User User { get; set; }

 

22

public Professor Professor { get; set; }

 

23

}

 

 

8

 

В этой связи между классами класс UserProfile является дочерним или подчиненным по отношению к классу User. И чтобы установить связь одни к одному, у подчиненного класса устанавливается свойство идентификатора, которое называется также, как и идентификатор в основном классе. То есть в классе User свойство называется Id, то и в UserProfile

также свойство называется Id. Если бы в классе User свойство называлось бы

UserId, то такое же название должно было быть и в UserProfile.

И в классе UserProfile над этим свойством Id устанавливаются два атрибута: [Key], который показывает, то это первичный ключ, и

[ForeignKey], который показывает, что это также и внешний ключ. Причем

внешний ключ к таблице объектов User.

 

 

Соответственно классы User и UserProfile имеют ссылки друг на

друга.

 

 

 

 

 

В классе контекста определяются свойства для взаимодействия с

таблицами в базе данных:

 

 

 

 

 

 

Листинг 17.25

 

 

 

 

 

1

public class UserContext : DbContext

 

 

2

{

 

 

 

 

3

public UserContext()

 

 

 

4

{ }

 

 

 

 

5

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

 

 

6

public DbSet<UserProfile> UserProfiles { get; set; }

 

 

7

public DbSet<Professor> Professors { get; set; }

 

 

8

public DbSet<Thesis> Theses { get; set; }

 

 

9

}

 

 

 

 

 

Для этих классов контекст данных будет создавать следующую таблицу

UserProfiles:

 

 

 

 

 

 

 

Листинг 17.26

 

 

 

1

CREATE TABLE [dbo].[UserProfiles] (

 

 

2

[Id]

INT

NOT NULL,

 

 

3

[Name]

NVARCHAR (MAX) NULL,

 

 

4

[NumberGroup]

INT

NOT NULL,

 

 

5

[PersonalDate] NVARCHAR (MAX) NULL,

 

 

 

 

 

9

 

6

CONSTRAINT [PK_dbo.UserProfiles] PRIMARY KEY CLUSTERED ([Id]

 

ASC),

7

CONSTRAINT [FK_dbo.UserProfiles_dbo.Users_Id] FOREIGN KEY

 

([Id]) REFERENCES [dbo].[Users] ([Id])

8

);

Посмотрим, как работать с моделями с такой связью. Рассмотрим сценарий регистрации пользователей в информационную систему.

Создадим форму для регистрации пользователей:

Рисунок 1

10

Источник: https://studfile.net/preview/16573805/