Связь один ко многим в C#
Примеры раздела используют SQLite через пакет в файле проекта:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Data.Sqlite" Version="10.0.14" />
</ItemGroup>
</Project>
Связь один ко многим означает: одна строка родителя может иметь много дочерних, а каждая дочерняя указывает ровно на одного родителя.
В таблице книг колонка "author_id" повторяет
один и тот же номер автора. Два автора и три книги
с общими внешними ключами оформляют так:
using Microsoft.Data.Sqlite;
string dbPath = "otm_books.db";
if (File.Exists(dbPath))
{
File.Delete(dbPath);
}
using SqliteConnection db = new($"Data Source={dbPath}");
db.Open();
using (SqliteCommand pragma = db.CreateCommand())
{
pragma.CommandText = "PRAGMA foreign_keys = ON";
pragma.ExecuteNonQuery();
}
using (SqliteCommand cmd = db.CreateCommand())
{
cmd.CommandText = "CREATE TABLE IF NOT EXISTS authors (id INTEGER PRIMARY KEY, name TEXT NOT NULL)";
cmd.ExecuteNonQuery();
}
using (SqliteCommand cmd = db.CreateCommand())
{
cmd.CommandText = "CREATE TABLE IF NOT EXISTS books (id INTEGER PRIMARY KEY, author_id INTEGER NOT NULL, title TEXT NOT NULL, FOREIGN KEY (author_id) REFERENCES authors (id))";
cmd.ExecuteNonQuery();
}
using (SqliteCommand cmd = db.CreateCommand())
{
cmd.CommandText = "INSERT INTO authors (name) VALUES ($p1)";
cmd.Parameters.AddWithValue("$p1", "Mira Cole");
cmd.ExecuteNonQuery();
}
using (SqliteCommand cmd = db.CreateCommand())
{
cmd.CommandText = "INSERT INTO authors (name) VALUES ($p1)";
cmd.Parameters.AddWithValue("$p1", "Jon Reed");
cmd.ExecuteNonQuery();
}
using (SqliteCommand cmd = db.CreateCommand())
{
cmd.CommandText = "INSERT INTO books (author_id, title) VALUES ($p1, $p2)";
cmd.Parameters.AddWithValue("$p1", 1);
cmd.Parameters.AddWithValue("$p2", "Quiet Harbor");
cmd.ExecuteNonQuery();
}
using (SqliteCommand cmd = db.CreateCommand())
{
cmd.CommandText = "INSERT INTO books (author_id, title) VALUES ($p1, $p2)";
cmd.Parameters.AddWithValue("$p1", 1);
cmd.Parameters.AddWithValue("$p2", "Stone Path");
cmd.ExecuteNonQuery();
}
using (SqliteCommand cmd = db.CreateCommand())
{
cmd.CommandText = "INSERT INTO books (author_id, title) VALUES ($p1, $p2)";
cmd.Parameters.AddWithValue("$p1", 2);
cmd.Parameters.AddWithValue("$p2", "Wide Field");
cmd.ExecuteNonQuery();
}
Подсчет книг у автора выполняют фильтром по
"author_id". У "Mira Cole" запрос
возвращает число 2:
using Microsoft.Data.Sqlite;
string dbPath = "otm_books.db";
if (File.Exists(dbPath))
{
File.Delete(dbPath);
}
using SqliteConnection db = new($"Data Source={dbPath}");
db.Open();
using (SqliteCommand pragma = db.CreateCommand())
{
pragma.CommandText = "PRAGMA foreign_keys = ON";
pragma.ExecuteNonQuery();
}
using (SqliteCommand cmd = db.CreateCommand())
{
cmd.CommandText = "CREATE TABLE IF NOT EXISTS authors (id INTEGER PRIMARY KEY, name TEXT NOT NULL)";
cmd.ExecuteNonQuery();
}
using (SqliteCommand cmd = db.CreateCommand())
{
cmd.CommandText = "CREATE TABLE IF NOT EXISTS books (id INTEGER PRIMARY KEY, author_id INTEGER NOT NULL, title TEXT NOT NULL, FOREIGN KEY (author_id) REFERENCES authors (id))";
cmd.ExecuteNonQuery();
}
using (SqliteCommand cmd = db.CreateCommand())
{
cmd.CommandText = "INSERT INTO authors (name) VALUES ($p1)";
cmd.Parameters.AddWithValue("$p1", "Mira Cole");
cmd.ExecuteNonQuery();
}
using (SqliteCommand cmd = db.CreateCommand())
{
cmd.CommandText = "INSERT INTO books (author_id, title) VALUES ($p1, $p2)";
cmd.Parameters.AddWithValue("$p1", 1);
cmd.Parameters.AddWithValue("$p2", "Quiet Harbor");
cmd.ExecuteNonQuery();
}
using (SqliteCommand cmd = db.CreateCommand())
{
cmd.CommandText = "INSERT INTO books (author_id, title) VALUES ($p1, $p2)";
cmd.Parameters.AddWithValue("$p1", 1);
cmd.Parameters.AddWithValue("$p2", "Stone Path");
cmd.ExecuteNonQuery();
}
using (SqliteCommand cmd = db.CreateCommand())
{
cmd.CommandText = "SELECT COUNT(*) FROM books WHERE author_id = $p1";
cmd.Parameters.AddWithValue("$p1", 1);
using SqliteDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
Console.WriteLine(reader.GetValue(0)); // выведет 2
}
}
В базе "otm_labs.db" создайте лабораторию
"North Lab" и три прибора этой лаборатории.
Выведите, сколько приборов к ней привязано.
Создайте "otm_brands.db" с таблицами
"brands" и "models". Одной марке
сопоставьте три модели и выведите их названия.