Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка ПИ Программирование на С# _Хотов.docx
Скачиваний:
12
Добавлен:
01.07.2025
Размер:
2 Мб
Скачать
☆
        1. Строка подключения в Model First и Database First

При использовании подходов Model First и Database First строка подключения выглядит иначе. Например:

1

2

3

4

5

6

7

<connectionStrings>

   <add name="persondbEntities"  providerName="System.Data.EntityClient"

   connectionString="metadata=res://*/Person.csdl|res://*/Person.ssdl|res://*/Person.msl;provider=System.Data.SqlClient;

       provider connection string="data source=HP-PC\SQLEXPRESS;

       initial catalog=persondb;integrated security=True;

       MultipleActiveResultSets=True;App=EntityFramework"" />

 </connectionStrings>

Здесь для нас важны следующие параметры строки подключения:

  • параметр metadata, содержащий метаданные модели ( так как в данном случае модель называется Person, то метаданные включают ресурсы Person.csdl, Person.ssdl, Person.msl)

  • параметр data source также устанавливает сервер MS SQL

  • а параметр initial catalog также устанавливает каталог базы данных

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

      1. Навигационные свойства и lazy loading

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

Допустим, для каждого футболиста может быть определена футбольная команда, в которой он играет. И, наоборот, в одной футбольной команде могут играть несколько футболистов. То есть в данном случае у нас связь один-ко-многим (one-to-many).

Например, у нас определен следующий класс футбольной команды Team:

1

2

3

4

5

6

class Team

{

    public int Id { get; set; }

    public string Name { get; set; } // название команды

    public string Coach { get; set; } // тренер

}

А класс Player, описывающий футболиста, мог бы выглядеть следующим образом:

1

2

3

4

5

6

7

8

9

10

class Player

{

    public int Id { get; set; }

    public string Name { get; set; }

    public string Position { get; set; }

    public int Age { get; set; }

 

    public int? TeamId { get; set; }

    public Team Team { get; set; }

}

Кроме обычных свойств типа Name, Position и Age здесь также определен внешний ключ. Внешний ключ состоит из обычного свойства и навигационного.

Свойство public Team Team { get; set; } в классе Player называется навигационным свойством - при получении данных об игроке оно будет автоматически получать данные из БД.

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

  • Имя_навигационного_свойства+Имя ключа из связанной таблицы - в нашем случае имя навигационного свойства Team, а ключа из модели Team - Id, поэтому в нашем случае нам надо обозвать свойство TeamId, что собственно и было сделано в вышеприведенном коде.

  • Имя_класса_связанной_таблицы+Имя ключа из связанной таблицы - в нашем случае класс Team, а ключа из модели Team - Id, поэтому опять же в этом случае получается TeamId

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

1

2

3

4

5

6

7

8

9

CREATE TABLE [dbo].[Players] (

    [Id]       INT            IDENTITY (1, 1) NOT NULL,

    [Name]     NVARCHAR (MAX) NULL,

    [Position] NVARCHAR (MAX) NULL,

    [Age]      INT            NOT NULL,

    [TeamId]   INT            NULL,

    CONSTRAINT [PK_dbo.Players] PRIMARY KEY CLUSTERED ([Id] ASC),

    CONSTRAINT [FK_dbo.Players_dbo.Teams_TeamId] FOREIGN KEY ([TeamId]) REFERENCES [dbo].[Teams] ([Id])

);

При определении внешнего ключа нужно иметь в виду следующее. Если тип обычного свойства во внешнем ключе определяется как int?, то есть допускает значения null, то при создании базы данных соответствующее поле так будет принимать значения NULL: [TeamId] INT NULL.

Однако если мы изменим в классе Player тип TeamId на просто int: public int TeamId { get; set; }, то в этом случае соответствующее поле имело бы ограничение NOT NULL, а внешний ключ определял бы каскадное удаление:

1

2

3

4

5

6

7

8

9

CREATE TABLE [dbo].[Players] (

    [Id]       INT            IDENTITY (1, 1) NOT NULL,

    [Name]     NVARCHAR (MAX) NULL,

    [Position] NVARCHAR (MAX) NULL,

    [Age]      INT            NOT NULL,

    [TeamId]   INT            NOT NULL,

    CONSTRAINT [PK_dbo.Players] PRIMARY KEY CLUSTERED ([Id] ASC),

    CONSTRAINT [FK_dbo.Players_dbo.Teams_TeamId] FOREIGN KEY ([TeamId]) REFERENCES [dbo].[Teams] ([Id]) ON DELETE CASCADE

);