From 5764ef8944c54b9338ea73757fe694f6ddd88fed Mon Sep 17 00:00:00 2001
From: Jakub <261062549+JakubFlejszar@users.noreply.github.com>
Date: Wed, 2 Sep 2026 23:56:53 +0200
Subject: [PATCH] completed
---
Phone Book/Phone Book.slnx | 3 +
Phone Book/Phone Book/CategoryController.cs | 58 ++++
Phone Book/Phone Book/ContactContext.cs | 30 ++
Phone Book/Phone Book/ContactController.cs | 58 ++++
Phone Book/Phone Book/Menu.cs | 323 ++++++++++++++++++
Phone Book/Phone Book/MenuValidation.cs | 44 +++
.../20260902212718_InitialCreate.Designer.cs | 130 +++++++
.../20260902212718_InitialCreate.cs | 85 +++++
.../Migrations/ContactContextModelSnapshot.cs | 127 +++++++
Phone Book/Phone Book/Models/Category.cs | 11 +
Phone Book/Phone Book/Models/Contact.cs | 14 +
Phone Book/Phone Book/PhoneBook.csproj | 21 ++
Phone Book/Phone Book/Program.cs | 9 +
13 files changed, 913 insertions(+)
create mode 100644 Phone Book/Phone Book.slnx
create mode 100644 Phone Book/Phone Book/CategoryController.cs
create mode 100644 Phone Book/Phone Book/ContactContext.cs
create mode 100644 Phone Book/Phone Book/ContactController.cs
create mode 100644 Phone Book/Phone Book/Menu.cs
create mode 100644 Phone Book/Phone Book/MenuValidation.cs
create mode 100644 Phone Book/Phone Book/Migrations/20260902212718_InitialCreate.Designer.cs
create mode 100644 Phone Book/Phone Book/Migrations/20260902212718_InitialCreate.cs
create mode 100644 Phone Book/Phone Book/Migrations/ContactContextModelSnapshot.cs
create mode 100644 Phone Book/Phone Book/Models/Category.cs
create mode 100644 Phone Book/Phone Book/Models/Contact.cs
create mode 100644 Phone Book/Phone Book/PhoneBook.csproj
create mode 100644 Phone Book/Phone Book/Program.cs
diff --git a/Phone Book/Phone Book.slnx b/Phone Book/Phone Book.slnx
new file mode 100644
index 00000000..abd71e69
--- /dev/null
+++ b/Phone Book/Phone Book.slnx
@@ -0,0 +1,3 @@
+
+
+
diff --git a/Phone Book/Phone Book/CategoryController.cs b/Phone Book/Phone Book/CategoryController.cs
new file mode 100644
index 00000000..036eb8fa
--- /dev/null
+++ b/Phone Book/Phone Book/CategoryController.cs
@@ -0,0 +1,58 @@
+using Microsoft.EntityFrameworkCore;
+using Phone_Book.Models;
+using Spectre.Console;
+
+namespace PhoneBook
+{
+ internal class CategoryController
+ {
+ public void CreateCategory(Category userCategory)
+ {
+ using var db = new ContactContext();
+ db.Categories.Add(userCategory);
+
+ SaveChanges(db);
+ }
+
+ public List GetAllCategories()
+ {
+ using var db = new ContactContext();
+ List categories = db.Categories.ToList();
+ return categories;
+ }
+
+ public void UpdateCategory(Category userCategory)
+ {
+ using var db = new ContactContext();
+ db.Categories.Update(userCategory);
+
+ SaveChanges(db);
+ }
+
+ public void DeleteCategory(Category userCategory)
+ {
+ using var db = new ContactContext();
+ db.Categories.Remove(userCategory);
+
+ SaveChanges(db);
+ }
+
+ public void SaveChanges(ContactContext db)
+ {
+ try
+ {
+ db.SaveChanges();
+ }
+ catch (DbUpdateConcurrencyException)
+ {
+ AnsiConsole.MarkupLine("[Red]ERROR [/]Couldn't save changes");
+ Environment.Exit(0);
+ }
+ catch (DbUpdateException)
+ {
+ AnsiConsole.MarkupLine("[Red]ERROR [/]Couldn't save changes");
+ Environment.Exit(0);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Phone Book/Phone Book/ContactContext.cs b/Phone Book/Phone Book/ContactContext.cs
new file mode 100644
index 00000000..9a51dcd3
--- /dev/null
+++ b/Phone Book/Phone Book/ContactContext.cs
@@ -0,0 +1,30 @@
+using Microsoft.EntityFrameworkCore;
+using Phone_Book.Models;
+using PhoneBook.Models;
+
+namespace PhoneBook
+{
+ public class ContactContext : DbContext
+ {
+ public DbSet Contacts { get; set; }
+ public DbSet Categories { get; set; }
+
+ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
+ {
+ optionsBuilder.UseSqlServer("Data Source=localhost; Initial Catalog=PhoneBook; Integrated Security=True; TrustServerCertificate=True;");
+ }
+
+ protected override void OnModelCreating(ModelBuilder modelBuilder)
+ {
+ modelBuilder.Entity().HasOne(contact => contact.Category).WithMany(category => category.Contacts).HasForeignKey(contact => contact.CategoryId).OnDelete(DeleteBehavior.Cascade);
+
+ modelBuilder.Entity().HasData(
+ new Contact { CategoryId = 2, Id = 1, PhoneNumber = "934568035", Email = "johnjohnson@gmail.com", ContactName = "John" },
+ new Contact { CategoryId = 1, Id = 2, PhoneNumber = "324532653", Email = "jankowalski@yahoo.com", ContactName = "Jan" },
+ new Contact { CategoryId = 1, Id = 3, PhoneNumber = "934568035", Email = "karen609@outlook.com", ContactName = "Karen" });
+ modelBuilder.Entity().HasData(
+ new Category { Id = 1, Name = "Friends" },
+ new Category { Id = 2, Name = "Family" });
+ }
+ }
+}
\ No newline at end of file
diff --git a/Phone Book/Phone Book/ContactController.cs b/Phone Book/Phone Book/ContactController.cs
new file mode 100644
index 00000000..bae8804d
--- /dev/null
+++ b/Phone Book/Phone Book/ContactController.cs
@@ -0,0 +1,58 @@
+using Microsoft.EntityFrameworkCore;
+using PhoneBook.Models;
+using Spectre.Console;
+
+namespace PhoneBook
+{
+ internal class ContactController
+ {
+ public void CreateContact(Contact userContact)
+ {
+ using var db = new ContactContext();
+ db.Contacts.Add(userContact);
+
+ SaveChanges(db);
+ }
+
+ public List GetAllContacts()
+ {
+ using var db = new ContactContext();
+ List contacts = db.Contacts.Include(contact => contact.Category).ToList();
+ return contacts;
+ }
+
+ public void UpdateContact(Contact userContact)
+ {
+ using var db = new ContactContext();
+ db.Contacts.Update(userContact);
+
+ SaveChanges(db);
+ }
+
+ public void DeleteContact(Contact userContact)
+ {
+ using var db = new ContactContext();
+ db.Contacts.Remove(userContact);
+
+ SaveChanges(db);
+ }
+
+ public void SaveChanges(ContactContext db)
+ {
+ try
+ {
+ db.SaveChanges();
+ }
+ catch (DbUpdateConcurrencyException)
+ {
+ AnsiConsole.MarkupLine("[Red]ERROR [/]Couldn't save changes");
+ Environment.Exit(0);
+ }
+ catch (DbUpdateException)
+ {
+ AnsiConsole.MarkupLine("[Red]ERROR [/]Couldn't save changes");
+ Environment.Exit(0);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Phone Book/Phone Book/Menu.cs b/Phone Book/Phone Book/Menu.cs
new file mode 100644
index 00000000..5966a3a3
--- /dev/null
+++ b/Phone Book/Phone Book/Menu.cs
@@ -0,0 +1,323 @@
+using Phone_Book.Models;
+using PhoneBook.Models;
+using Spectre.Console;
+
+namespace PhoneBook
+{
+ internal class Menu
+ {
+ private Contact userContact = new Contact();
+ private Category userCategory = new Category();
+ private ContactController contactController = new ContactController();
+ private CategoryController categoryController = new CategoryController();
+ private bool isRunning = true;
+
+ public Menu()
+ {
+ while (isRunning)
+ {
+ var actionSelection = new SelectionPrompt()
+ .Title("Choose action")
+ .PageSize(10)
+ .AddChoices("View contacts", "Create contact", "Delete contact", "Update contact",
+ "View categories", "Create category", "Delete category", "Update category", "Exit");
+
+ string selectedAction = AnsiConsole.Prompt(actionSelection);
+
+ switch (selectedAction)
+ {
+ case "View contacts":
+ ViewContacts();
+ break;
+
+ case "Create contact":
+ CreateContact();
+ break;
+
+ case "Delete contact":
+ DeleteContact();
+ break;
+
+ case "Update contact":
+ UpdateContact();
+ break;
+
+ case "View categories":
+ ViewCategories();
+ break;
+
+ case "Create category":
+ CreateCategory();
+ break;
+
+ case "Delete category":
+ DeleteCategory();
+ break;
+
+ case "Update category":
+ UpdateCategory();
+ break;
+
+ case "Exit":
+ Console.Clear();
+ Console.WriteLine("Goodbye");
+ isRunning = false;
+ break;
+ }
+ }
+ }
+
+ private List ViewCategories()
+ {
+ Console.Clear();
+ List categoriesList = categoryController.GetAllCategories();
+ if (categoriesList.Count == 0)
+ {
+ AnsiConsole.MarkupLine("Currently you don't have any categories\n");
+ }
+ else
+ {
+ var viewCategoriesTable = new Table()
+ .RoundedBorder()
+ .ShowRowSeparators()
+ .Title("[Blue]Categories List[/]")
+ .AddColumns("No.", "Category name");
+ int number = 1;
+ foreach (Category category in categoriesList)
+ {
+ string stringNumber = Convert.ToString(number);
+ viewCategoriesTable.AddRow(stringNumber, category.Name);
+ number++;
+ }
+ AnsiConsole.Write(viewCategoriesTable);
+ }
+ return categoriesList;
+ }
+
+ private void CreateCategory()
+ {
+ Console.Clear();
+ AnsiConsole.MarkupLine("Creating new [Blue]category[/]");
+ string categoryName = AnsiConsole.Ask("Please type [DarkRed_1]name for new category[/]");
+ userCategory.Name = categoryName;
+
+ categoryController.CreateCategory(userCategory);
+ }
+
+ private void DeleteCategory()
+ {
+ Console.Clear();
+ List categoryList = ViewCategories();
+ if (categoryList.Count == 0)
+ {
+ return;
+ }
+ int deleteNo = 0;
+ int id = 0;
+ try
+ {
+ deleteNo = AnsiConsole.Ask("Please type number of [Blue]category[/] that you want to [DarkRed_1]delete[/]");
+ int chosenNo = deleteNo - 1;
+ id = categoryList[chosenNo].Id;
+ userCategory.Id = id;
+ categoryController.DeleteCategory(userCategory);
+ }
+ catch (ArgumentOutOfRangeException)
+ {
+ AnsiConsole.MarkupLine($"There is no category with such [DarkRed_1]number, {deleteNo}[/]");
+ return;
+ }
+ }
+
+ private void UpdateCategory()
+ {
+ Console.Clear();
+ List categories = ViewCategories();
+ if (categories.Count == 0)
+ {
+ return;
+ }
+ int updateNo = 0;
+ int id = 0;
+ try
+ {
+ updateNo = AnsiConsole.Ask("Please type number of [Blue]category[/] that you want to [DarkRed_1]update[/]");
+ int chosenNo = updateNo - 1;
+ id = categories[chosenNo].Id;
+ }
+ catch (ArgumentOutOfRangeException)
+ {
+ AnsiConsole.MarkupLine($"There is no category with such [DarkRed_1]number, {updateNo}[/]");
+ return;
+ }
+ string newCategoryName = AnsiConsole.Ask("Please type new [DarkRed_1]name for category[/]");
+ userCategory.Name = newCategoryName;
+ userCategory.Id = id;
+ categoryController.UpdateCategory(userCategory);
+ }
+
+ private List ViewContacts()
+ {
+ Console.Clear();
+
+ List contactsList = contactController.GetAllContacts();
+ if (contactsList.Count == 0)
+ {
+ AnsiConsole.MarkupLine("Currently you don't have any contacts\n");
+ }
+ else
+ {
+ var viewContactsTable = new Table()
+ .RoundedBorder()
+ .ShowRowSeparators()
+ .Title("[Blue]Contacts List[/]")
+ .AddColumns("Category", "No.", "Contact name", "Email", "Phone number");
+ int number = 1;
+ foreach (Contact contact in contactsList)
+ {
+ string stringNumber = Convert.ToString(number);
+ viewContactsTable.AddRow(contact.Category.Name, stringNumber, contact.ContactName, contact.Email, contact.PhoneNumber);
+ number++;
+ }
+ AnsiConsole.Write(viewContactsTable);
+ }
+
+ return contactsList;
+ }
+
+ private void CreateContact()
+ {
+ Console.Clear();
+
+ List categories = ViewCategories();
+
+ if (categories.Count == 0)
+ {
+ AnsiConsole.MarkupLine("[Red]Error![/] You have to create any [Blue]category[/], before making [Blue]contact[/]");
+ return;
+ }
+ var categorySelect = new SelectionPrompt()
+ .Title("Choose [Blue]category[/] to insert new contact")
+ .PageSize(6);
+
+ foreach (Category category in categories)
+ {
+ categorySelect.AddChoice(category.Name);
+ }
+ string selectedCategory = AnsiConsole.Prompt(categorySelect);
+
+ var categoryFromList = categories.FirstOrDefault(category => category.Name == selectedCategory);
+
+ int categoryId = categoryFromList.Id;
+
+ AnsiConsole.MarkupLine("Creating new [Blue]contact[/]");
+ string contactName = AnsiConsole.Ask("Please type [DarkRed_1]name for new contact[/]");
+ string phoneNumber = AnsiConsole.Ask("Please type [DarkRed_1]phone number for new contact[/]");
+ bool isPhoneCorrect = MenuValidation.PhoneValidation(phoneNumber);
+ while (!isPhoneCorrect)
+ {
+ phoneNumber = AnsiConsole.Ask("Please type [DarkRed_1]phone number for new contact[/]");
+ isPhoneCorrect = MenuValidation.PhoneValidation(phoneNumber);
+ }
+ string email = AnsiConsole.Ask("Please type [DarkRed_1]email for new contact[/](eg. name@gmail.com)");
+ bool isEmailCorrect = MenuValidation.EmailValidation(email);
+ while (!isEmailCorrect)
+ {
+ email = AnsiConsole.Ask("Please type [DarkRed_1]email for new contact[/]");
+ isEmailCorrect = MenuValidation.EmailValidation(email);
+ }
+ userContact.CategoryId = categoryId;
+ userContact.ContactName = contactName;
+ userContact.PhoneNumber = phoneNumber;
+ userContact.Email = email;
+ contactController.CreateContact(userContact);
+ }
+
+ private void DeleteContact()
+ {
+ List contactsList = ViewContacts();
+ if (contactsList.Count == 0)
+ {
+ return;
+ }
+ int deleteNo = 0;
+ try
+ {
+ deleteNo = AnsiConsole.Ask("Please type number of [Blue]contact[/] that you want to [DarkRed_1]delete[/]");
+ int chosenNo = deleteNo - 1;
+ int id = contactsList[chosenNo].Id;
+ userContact.Id = id;
+ contactController.DeleteContact(userContact);
+ }
+ catch (ArgumentOutOfRangeException)
+ {
+ AnsiConsole.MarkupLine($"There is no contact with such [DarkRed_1]number, {deleteNo}[/]");
+ }
+ }
+
+ private void UpdateContact()
+ {
+ List categoriesList = categoryController.GetAllCategories();
+
+ var categorySelect = new SelectionPrompt()
+ .Title("Choose [Blue]category[/]")
+ .PageSize(6);
+ foreach (Category category in categoriesList)
+ {
+ categorySelect.AddChoice(category.Name);
+ }
+ var selectedCategory = AnsiConsole.Prompt(categorySelect);
+
+ var categoryFromList = categoriesList.FirstOrDefault(category => category.Name == selectedCategory);
+
+ int categoryId = categoryFromList.Id;
+
+ List contactsList = contactController.GetAllContacts();
+
+ contactsList = contactsList
+ .Where(contact => contact.CategoryId == categoryId)
+ .ToList();
+
+ if (contactsList.Count == 0)
+ {
+ AnsiConsole.MarkupLine("[Red]Error![/] You don't have any contacts in this category");
+ return;
+ }
+ int id = 0;
+ var contactSelect = new SelectionPrompt()
+ .Title("Choose [Blue]contact[/]")
+ .PageSize(6);
+ foreach (Contact contact in contactsList)
+ {
+ contactSelect.AddChoice(contact.ContactName);
+ }
+ string selectedContact = AnsiConsole.Prompt(contactSelect);
+
+ var contactFromList = contactsList.FirstOrDefault(contact => contact.ContactName == selectedContact);
+
+ id = contactFromList.Id;
+
+ Console.Clear();
+ string newContactName = AnsiConsole.Ask("Please type new [DarkRed_1]name for contact[/]");
+ string newPhoneNumber = AnsiConsole.Ask("Please type new [DarkRed_1]phone number for contact[/]");
+ bool isPhoneCorrect = MenuValidation.PhoneValidation(newPhoneNumber);
+ while (!isPhoneCorrect)
+ {
+ newPhoneNumber = AnsiConsole.Ask("Please type [DarkRed_1]phone number for new contact[/]");
+ isPhoneCorrect = MenuValidation.PhoneValidation(newPhoneNumber);
+ }
+ string newEmail = AnsiConsole.Ask("Please type new [DarkRed_1]email for contact[/]");
+ bool isEmailCorrect = MenuValidation.EmailValidation(newEmail);
+ while (!isEmailCorrect)
+ {
+ newEmail = AnsiConsole.Ask("Please type [DarkRed_1]email for new contact[/]");
+ isEmailCorrect = MenuValidation.EmailValidation(newEmail);
+ }
+ userContact.Id = id;
+ userContact.ContactName = newContactName;
+ userContact.PhoneNumber = newPhoneNumber;
+ userContact.Email = newEmail;
+ contactController.UpdateContact(userContact);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Phone Book/Phone Book/MenuValidation.cs b/Phone Book/Phone Book/MenuValidation.cs
new file mode 100644
index 00000000..1e20762e
--- /dev/null
+++ b/Phone Book/Phone Book/MenuValidation.cs
@@ -0,0 +1,44 @@
+using System.Net.Mail;
+
+namespace PhoneBook
+{
+ internal static class MenuValidation
+ {
+ public static bool EmailValidation(string email)
+ {
+ MailAddress emailAddress;
+ bool correctEmailBool = MailAddress.TryCreate(email, out emailAddress);
+ if (correctEmailBool)
+ {
+ if (emailAddress.Host.Contains("."))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ return false;
+ }
+
+ public static bool PhoneValidation(string phoneNumber)
+ {
+ bool isPhoneNumberEmpty = string.IsNullOrWhiteSpace(phoneNumber);
+ if (!isPhoneNumberEmpty)
+ {
+ if (phoneNumber.StartsWith("+"))
+ {
+ if (phoneNumber.Length > 1)
+ {
+ bool isNumericPlus = phoneNumber.Skip(1).All(char.IsDigit);
+ return isNumericPlus;
+ }
+ }
+ bool isNumeric = phoneNumber.All(char.IsDigit);
+ return isNumeric;
+ }
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Phone Book/Phone Book/Migrations/20260902212718_InitialCreate.Designer.cs b/Phone Book/Phone Book/Migrations/20260902212718_InitialCreate.Designer.cs
new file mode 100644
index 00000000..0b23dfa1
--- /dev/null
+++ b/Phone Book/Phone Book/Migrations/20260902212718_InitialCreate.Designer.cs
@@ -0,0 +1,130 @@
+//
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using PhoneBook;
+
+#nullable disable
+
+namespace Phone_Book.Migrations
+{
+ [DbContext(typeof(ContactContext))]
+ [Migration("20260902212718_InitialCreate")]
+ partial class InitialCreate
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "10.0.11")
+ .HasAnnotation("Relational:MaxIdentifierLength", 128);
+
+ SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
+
+ modelBuilder.Entity("PhoneBook.Models.Contact", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"));
+
+ b.Property("CategoryId")
+ .HasColumnType("int");
+
+ b.Property("ContactName")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("Email")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("PhoneNumber")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CategoryId");
+
+ b.ToTable("Contacts");
+
+ b.HasData(
+ new
+ {
+ Id = 1,
+ CategoryId = 2,
+ ContactName = "John",
+ Email = "johnjohnson@gmail.com",
+ PhoneNumber = "934568035"
+ },
+ new
+ {
+ Id = 2,
+ CategoryId = 1,
+ ContactName = "Jan",
+ Email = "jankowalski@yahoo.com",
+ PhoneNumber = "324532653"
+ },
+ new
+ {
+ Id = 3,
+ CategoryId = 1,
+ ContactName = "Karen",
+ Email = "karen609@outlook.com",
+ PhoneNumber = "934568035"
+ });
+ });
+
+ modelBuilder.Entity("Phone_Book.Models.Category", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"));
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.HasKey("Id");
+
+ b.ToTable("Categories");
+
+ b.HasData(
+ new
+ {
+ Id = 1,
+ Name = "Friends"
+ },
+ new
+ {
+ Id = 2,
+ Name = "Family"
+ });
+ });
+
+ modelBuilder.Entity("PhoneBook.Models.Contact", b =>
+ {
+ b.HasOne("Phone_Book.Models.Category", "Category")
+ .WithMany("Contacts")
+ .HasForeignKey("CategoryId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Category");
+ });
+
+ modelBuilder.Entity("Phone_Book.Models.Category", b =>
+ {
+ b.Navigation("Contacts");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/Phone Book/Phone Book/Migrations/20260902212718_InitialCreate.cs b/Phone Book/Phone Book/Migrations/20260902212718_InitialCreate.cs
new file mode 100644
index 00000000..cdaeacd7
--- /dev/null
+++ b/Phone Book/Phone Book/Migrations/20260902212718_InitialCreate.cs
@@ -0,0 +1,85 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
+
+namespace Phone_Book.Migrations
+{
+ ///
+ public partial class InitialCreate : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.CreateTable(
+ name: "Categories",
+ columns: table => new
+ {
+ Id = table.Column(type: "int", nullable: false)
+ .Annotation("SqlServer:Identity", "1, 1"),
+ Name = table.Column(type: "nvarchar(max)", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Categories", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "Contacts",
+ columns: table => new
+ {
+ Id = table.Column(type: "int", nullable: false)
+ .Annotation("SqlServer:Identity", "1, 1"),
+ CategoryId = table.Column(type: "int", nullable: false),
+ PhoneNumber = table.Column(type: "nvarchar(max)", nullable: false),
+ Email = table.Column(type: "nvarchar(max)", nullable: false),
+ ContactName = table.Column(type: "nvarchar(max)", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Contacts", x => x.Id);
+ table.ForeignKey(
+ name: "FK_Contacts_Categories_CategoryId",
+ column: x => x.CategoryId,
+ principalTable: "Categories",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.InsertData(
+ table: "Categories",
+ columns: new[] { "Id", "Name" },
+ values: new object[,]
+ {
+ { 1, "Friends" },
+ { 2, "Family" }
+ });
+
+ migrationBuilder.InsertData(
+ table: "Contacts",
+ columns: new[] { "Id", "CategoryId", "ContactName", "Email", "PhoneNumber" },
+ values: new object[,]
+ {
+ { 1, 2, "John", "johnjohnson@gmail.com", "934568035" },
+ { 2, 1, "Jan", "jankowalski@yahoo.com", "324532653" },
+ { 3, 1, "Karen", "karen609@outlook.com", "934568035" }
+ });
+
+ migrationBuilder.CreateIndex(
+ name: "IX_Contacts_CategoryId",
+ table: "Contacts",
+ column: "CategoryId");
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropTable(
+ name: "Contacts");
+
+ migrationBuilder.DropTable(
+ name: "Categories");
+ }
+ }
+}
diff --git a/Phone Book/Phone Book/Migrations/ContactContextModelSnapshot.cs b/Phone Book/Phone Book/Migrations/ContactContextModelSnapshot.cs
new file mode 100644
index 00000000..4dc73aa9
--- /dev/null
+++ b/Phone Book/Phone Book/Migrations/ContactContextModelSnapshot.cs
@@ -0,0 +1,127 @@
+//
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using PhoneBook;
+
+#nullable disable
+
+namespace Phone_Book.Migrations
+{
+ [DbContext(typeof(ContactContext))]
+ partial class ContactContextModelSnapshot : ModelSnapshot
+ {
+ protected override void BuildModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "10.0.11")
+ .HasAnnotation("Relational:MaxIdentifierLength", 128);
+
+ SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
+
+ modelBuilder.Entity("PhoneBook.Models.Contact", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"));
+
+ b.Property("CategoryId")
+ .HasColumnType("int");
+
+ b.Property("ContactName")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("Email")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("PhoneNumber")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CategoryId");
+
+ b.ToTable("Contacts");
+
+ b.HasData(
+ new
+ {
+ Id = 1,
+ CategoryId = 2,
+ ContactName = "John",
+ Email = "johnjohnson@gmail.com",
+ PhoneNumber = "934568035"
+ },
+ new
+ {
+ Id = 2,
+ CategoryId = 1,
+ ContactName = "Jan",
+ Email = "jankowalski@yahoo.com",
+ PhoneNumber = "324532653"
+ },
+ new
+ {
+ Id = 3,
+ CategoryId = 1,
+ ContactName = "Karen",
+ Email = "karen609@outlook.com",
+ PhoneNumber = "934568035"
+ });
+ });
+
+ modelBuilder.Entity("Phone_Book.Models.Category", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"));
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.HasKey("Id");
+
+ b.ToTable("Categories");
+
+ b.HasData(
+ new
+ {
+ Id = 1,
+ Name = "Friends"
+ },
+ new
+ {
+ Id = 2,
+ Name = "Family"
+ });
+ });
+
+ modelBuilder.Entity("PhoneBook.Models.Contact", b =>
+ {
+ b.HasOne("Phone_Book.Models.Category", "Category")
+ .WithMany("Contacts")
+ .HasForeignKey("CategoryId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Category");
+ });
+
+ modelBuilder.Entity("Phone_Book.Models.Category", b =>
+ {
+ b.Navigation("Contacts");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/Phone Book/Phone Book/Models/Category.cs b/Phone Book/Phone Book/Models/Category.cs
new file mode 100644
index 00000000..3b9dc9f8
--- /dev/null
+++ b/Phone Book/Phone Book/Models/Category.cs
@@ -0,0 +1,11 @@
+using PhoneBook.Models;
+
+namespace Phone_Book.Models
+{
+ public class Category
+ {
+ public int Id { get; set; }
+ public string Name { get; set; }
+ public List Contacts { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Phone Book/Phone Book/Models/Contact.cs b/Phone Book/Phone Book/Models/Contact.cs
new file mode 100644
index 00000000..f5af7bc5
--- /dev/null
+++ b/Phone Book/Phone Book/Models/Contact.cs
@@ -0,0 +1,14 @@
+using Phone_Book.Models;
+
+namespace PhoneBook.Models
+{
+ public class Contact
+ {
+ public Category Category { get; set; }
+ public int CategoryId { get; set; }
+ public int Id { get; set; }
+ public string PhoneNumber { get; set; }
+ public string Email { get; set; }
+ public string ContactName { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Phone Book/Phone Book/PhoneBook.csproj b/Phone Book/Phone Book/PhoneBook.csproj
new file mode 100644
index 00000000..53731fc2
--- /dev/null
+++ b/Phone Book/Phone Book/PhoneBook.csproj
@@ -0,0 +1,21 @@
+
+
+
+ Exe
+ net10.0
+ Phone_Book
+ enable
+ enable
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
diff --git a/Phone Book/Phone Book/Program.cs b/Phone Book/Phone Book/Program.cs
new file mode 100644
index 00000000..066b2ecc
--- /dev/null
+++ b/Phone Book/Phone Book/Program.cs
@@ -0,0 +1,9 @@
+namespace PhoneBook;
+
+internal static class Program
+{
+ private static void Main()
+ {
+ var menu = new Menu();
+ }
+}
\ No newline at end of file