Using C# Classes to Create a Database
In this lesson, we will be using class
es and List<>
to create an example
database to manage employees. We will create a menu system that will allow us to
C
reate, R
ead, U
pdate, and D
elete employees from this List.
Reviewing the starting code.
We will make a new project: dotnet new sdg-console -o SuncoastHumanResources
The code below is our starting point. It defines an Employee
class and
contains code to input the details of a single employee.
using System;namespace SuncoastHumanResources{class Employee{public string Name { get; set; }public int Department { get; set; }public int Salary { get; set; }public int MonthlySalary(){return Salary / 12;}}class Program{static void DisplayGreeting(){Console.WriteLine("----------------------------------------");Console.WriteLine(" Welcome to Our Employee Database ");Console.WriteLine("----------------------------------------");Console.WriteLine();Console.WriteLine();}static string PromptForString(string prompt){Console.Write(prompt);var userInput = Console.ReadLine();return userInput;}static int PromptForInteger(string prompt){Console.Write(prompt);int userInput;var isThisGoodInput = Int32.TryParse(Console.ReadLine(), out userInput);if (isThisGoodInput){return userInput;}else{Console.WriteLine("Sorry, that isn't a valid input, I'm using 0 as your answer.");return 0;}}static void Main(string[] args){var employee = new Employee();DisplayGreeting();employee.Name = PromptForString("What is your name? ");employee.Department = PromptForInteger("What is your department number? ");employee.Salary = PromptForInteger("What is your yearly salary (in dollars)? ");Console.WriteLine($"Hello, {employee.Name} you make {employee.MonthlySalary()} dollars per month.");}}}
While this is a good start, it lacks features. Most significantly, we can only
store one employee, so our Employee Database is not very useful. To improve it,
let's add a menu system to prompt the user to add, search, and delete employees.
We will keep all these employees in a List
and use class
es to organize our
code.
Adding a List
to store our employees
The List
we will create will look like this:
var employees = new List<Employee>();
We name the variable employees
, the plural of employee
to hint that this
variable stores a collection of things. While this isn't a mandate by the
language, choosing good names for our variables is a quality of a good developer
and a habit we should start early. We define this variable as a List
of things
that will all be instances of our Employee
class.
To put an employee in our list, we use the code: employees.Add(employee)
where
employee
is an instance of Employee
Now our code looks like this:
using System;using System.Collections.Generic;namespace SuncoastHumanResources{class Employee{public string Name { get; set; }public int Department { get; set; }public int Salary { get; set; }public int MonthlySalary(){return Salary / 12;}}class Program{static void DisplayGreeting(){Console.WriteLine("----------------------------------------");Console.WriteLine(" Welcome to Our Employee Database ");Console.WriteLine("----------------------------------------");Console.WriteLine();Console.WriteLine();}static string PromptForString(string prompt){Console.Write(prompt);var userInput = Console.ReadLine();return userInput;}static int PromptForInteger(string prompt){Console.Write(prompt);int userInput;var isThisGoodInput = Int32.TryParse(Console.ReadLine(), out userInput);if (isThisGoodInput){return userInput;}else{Console.WriteLine("Sorry, that isn't a valid input, I'm using 0 as your answer.");return 0;}}static void Main(string[] args){var employees = new List<Employee>();var employee = new Employee();DisplayGreeting();employee.Name = PromptForString("What is your name? ");employee.Department = PromptForInteger("What is your department number? ");employee.Salary = PromptForInteger("What is your yearly salary (in dollars)? ");employees.Add(employee);}}}
Let's make a simple menu
To make a menu, we'll introduce a keepGoing
variable which will track if the
user wishes to continue in our program. We will use this variable in a while
loop to determine when to stop the loop. Inside the loop, we will show a prompt
and use the existing code to ask the user for details on a new employee.
The menu allows the user to add employees to our list until they select the option to quit.
using System;using System.Collections.Generic;namespace SuncoastHumanResources{class Employee{public string Name { get; set; }public int Department { get; set; }public int Salary { get; set; }public int MonthlySalary(){return Salary / 12;}}class Program{static void DisplayGreeting(){Console.WriteLine("----------------------------------------");Console.WriteLine(" Welcome to Our Employee Database ");Console.WriteLine("----------------------------------------");Console.WriteLine();Console.WriteLine();}static string PromptForString(string prompt){Console.Write(prompt);var userInput = Console.ReadLine();return userInput;}static int PromptForInteger(string prompt){Console.Write(prompt);int userInput;var isThisGoodInput = Int32.TryParse(Console.ReadLine(), out userInput);if (isThisGoodInput){return userInput;}else{Console.WriteLine("Sorry, that isn't a valid input, I'm using 0 as your answer.");return 0;}}static void Main(string[] args){// Our list of employeesvar employees = new List<Employee>();DisplayGreeting();// Should we keep showing the menu?var keepGoing = true;// While the user hasn't said QUIT yetwhile (keepGoing) {// Insert a blank line then prompt them and get their answer (force uppercase)Console.WriteLine();Console.Write("What do you want to do? (A)dd an employee or (Q)uit: ");var choice = Console.ReadLine().ToUpper();if (choice == "Q") {// They said quit, so set our keepGoing to falsekeepGoing = false;} else {// Make a new employee objectvar employee = new Employee();// Prompt for values and save them in the employee's propertiesemployee.Name = PromptForString("What is your name? ");employee.Department = PromptForInteger("What is your department number? ");employee.Salary = PromptForInteger("What is your yearly salary (in dollars)? ");// Add it to the listemployees.Add(employee);}// end of the `while` statement}}}}
Add an option to show all the employees
Let's add a menu item to show all the employees in the database.
using System;using System.Collections.Generic;namespace SuncoastHumanResources{class Employee{public string Name { get; set; }public int Department { get; set; }public int Salary { get; set; }public int MonthlySalary(){return Salary / 12;}}class Program{static void DisplayGreeting(){Console.WriteLine("----------------------------------------");Console.WriteLine(" Welcome to Our Employee Database ");Console.WriteLine("----------------------------------------");Console.WriteLine();Console.WriteLine();}static string PromptForString(string prompt){Console.Write(prompt);var userInput = Console.ReadLine();return userInput;}static int PromptForInteger(string prompt){Console.Write(prompt);int userInput;var isThisGoodInput = Int32.TryParse(Console.ReadLine(), out userInput);if (isThisGoodInput){return userInput;}else{Console.WriteLine("Sorry, that isn't a valid input, I'm using 0 as your answer.");return 0;}}static void Main(string[] args){// Our list of employeesvar employees = new List<Employee>();// Should we keep showing the menu?var keepGoing = true;DisplayGreeting();// While the user hasn't said QUIT yetwhile (keepGoing) {// Insert a blank line then prompt them and get their answer (force uppercase)Console.WriteLine();Console.Write("What do you want to do? (A)dd an employee or (S)how all the employees or (Q)uit: ");var choice = Console.ReadLine().ToUpper();if (choice == "Q") {// They said quit, so set our keepGoing to falsekeepGoing = false;} else if (choice == "S") {// Loop through each employeeforeach(var employee in employees) {// And print detailsConsole.WriteLine($"{employee.Name} is in department {employee.Department} and makes ${employee.Salary}");}} else {// Make a new employee objectvar employee = new Employee();// Prompt for values and save them in the employee's propertiesemployee.Name = PromptForString("What is your name? ");employee.Department = PromptForInteger("What is your department number? ");employee.Salary = PromptForInteger("What is your yearly salary (in dollars)? ");// Add it to the listemployees.Add(employee);}// end of the `while` statement}}}}
Find an employee by name
Adding another menu option to find an employee by name. First, we prompt for the
name to search. We use a foreach
loop to look for an employee with a matching
name. If we find one, we update a variable named foundEmployee
which otherwise
will have the value null
. After the loop is done if foundEmployee
is null
,
we show the user a message; otherwise, we display the details of
foundEmployee
.
using System;using System.Collections.Generic;namespace SuncoastHumanResources{class Employee{public string Name { get; set; }public int Department { get; set; }public int Salary { get; set; }public int MonthlySalary(){return Salary / 12;}}class Program{static void DisplayGreeting(){Console.WriteLine("----------------------------------------");Console.WriteLine(" Welcome to Our Employee Database ");Console.WriteLine("----------------------------------------");Console.WriteLine();Console.WriteLine();}static string PromptForString(string prompt){Console.Write(prompt);var userInput = Console.ReadLine();return userInput;}static int PromptForInteger(string prompt){Console.Write(prompt);int userInput;var isThisGoodInput = Int32.TryParse(Console.ReadLine(), out userInput);if (isThisGoodInput){return userInput;}else{Console.WriteLine("Sorry, that isn't a valid input, I'm using 0 as your answer.");return 0;}}static void Main(string[] args){// Our list of employeesvar employees = new List<Employee>();// Should we keep showing the menu?var keepGoing = true;DisplayGreeting();// While the user hasn't said QUIT yetwhile (keepGoing) {// Insert a blank line then prompt them and get their answer (force uppercase)Console.WriteLine();Console.Write("What do you want to do? (A)dd an employee or (S)how all the employees or (F)ind an employee or (Q)uit: ");var choice = Console.ReadLine().ToUpper();if (choice == "Q") {// They said quit, so set our keepGoing to falsekeepGoing = false;} else if (choice == "F") {// Ask for the name of an employeevar name = PromptForString("What name are you looking for? ");// Make a new variable to store the found employee, initializing// to null which will indicate no match foundEmployee foundEmployee = null;// Go through all the employeesforeach(var employee in employees) {// If the name matchesif (employee.Name == name) {// ... then store this employee in the foundEmployee variablefoundEmployee = employee;}}// If the foundEmployee is still null, nothing was foundif (foundEmployee == null) {Console.WriteLine("No match found");} else {// Otherwise print details of the found employeeConsole.WriteLine($"{foundEmployee.Name} is in department {foundEmployee.Department} and makes ${foundEmployee.Salary}");}} else if (choice == "S") {// Loop through each employeeforeach(var employee in employees) {// And print detailsConsole.WriteLine($"{employee.Name} is in department {employee.Department} and makes ${employee.Salary}");}} else {// Make a new employee objectvar employee = new Employee();// Prompt for values and save them in the employee's propertiesemployee.Name = PromptForString("What is your name? ");employee.Department = PromptForInteger("What is your department number? ");employee.Salary = PromptForInteger("What is your yearly salary (in dollars)? ");// Add it to the listemployees.Add(employee);}// end of the `while` statement}}}}
Improving this code by adding LINQ
We can add using System.Linq
to the top of our code, then we can utilize
FirstOrDefault
for our searching code.
// Ask for the name of an employeevar name = PromptForString("What name are you looking for: ");// Make a new variable to store the found employee, initializing// to null, which will indicate no match foundEmployee foundEmployee = employees.FirstOrDefault(employee => employee.Name == name);// If the foundEmployee is still null, nothing was foundif (foundEmployee == null) {Console.WriteLine("No match found");} else {// Otherwise print details of the found employeeConsole.WriteLine($"{foundEmployee.Name} is in department {foundEmployee.Department} and makes ${foundEmployee.Salary}");}
Delete an employee and update an employee
These are two other features that our employee database might need. We'll leave these to you to add to the application if you'd like to try.
Refactoring the database features into a class
The functions for adding, searching, and displaying all the employees from the list exist in the main code. Extracting the code into a specific class to manage the list will increase the code's clarity and give specific places to implement new features.
We start by creating a class EmployeeDatabase
and move our List<Employee>
inside. We make this class property private
since we do not want code outside
of the class to access it. All the usage must come from the methods we create
and allow as public
. We then develop methods to perform the common actions we
need, GetAllEmployees
, FindOneEmployee
, AddEmployee
. Each of these methods
receives the data it needs and returns the data it provides. These methods
essentially create an API (Application Programming Interface) for how to use
this code.
By creating a class EmployeeDatabase
, we have isolated the code that has to do
with the list of employees. The organization of the class allows the database
implementation to change without modifying the code that uses it. For instance,
we could load and save the data from a data file. Any time we can change one
part of the system, for example, the employee database, without changing other
parts of the code, for example, the menu system, we have created a good
decoupling of our system's components.
using System;using System.Collections.Generic;namespace SuncoastHumanResources{class Employee{public string Name { get; set; }public int Department { get; set; }public int Salary { get; set; }public int MonthlySalary(){return Salary / 12;}}class EmployeeDatabase{// Keep a *private* copy of the employee list.//// We make this private since we don't want code from// outside this class to have access to it. All access// to this information comes through the methods of the// class.private List<Employee> employees = new List<Employee>();// Get a list of all the employeespublic List<Employee> GetAllEmployees(){return employees;}// Given an argument of an employee, add that employee// to the list of employees we are managing.public void AddEmployee(Employee newEmployee){employees.Add(newEmployee);}// Given a name as a string, look through the list of// employees. If we find one with a matching name, return// the employee. If nothing is found, return a null.public Employee FindOneEmployee(string name){// to null which will indicate no match foundEmployee foundEmployee = employees.FirstOrDefault(employee => employee.Name == name)// Return what we found (the employee or null)return foundEmployee;}}class Program{static void DisplayGreeting(){Console.WriteLine("----------------------------------------");Console.WriteLine(" Welcome to Our Employee Database ");Console.WriteLine("----------------------------------------");Console.WriteLine();Console.WriteLine();}static string PromptForString(string prompt){Console.Write(prompt);var userInput = Console.ReadLine();return userInput;}static int PromptForInteger(string prompt){Console.Write(prompt);int userInput;var isThisGoodInput = Int32.TryParse(Console.ReadLine(), out userInput);if (isThisGoodInput){return userInput;}else{Console.WriteLine("Sorry, that isn't a valid input, I'm using 0 as your answer.");return 0;}}static void Main(string[] args){// Our databasevar database = new EmployeeDatabase();// Should we keep showing the menu?var keepGoing = true;DisplayGreeting();// While the user hasn't said QUIT yetwhile (keepGoing) {// Insert a blank line then prompt them and get their answer (force uppercase)Console.WriteLine();Console.Write("What do you want to do? (A)dd an employee or (S)how all the employees or (F)ind an employee or (Q)uit: ");var choice = Console.ReadLine().ToUpper();if (choice == "Q") {// They said quit, so set our keepGoing to falsekeepGoing = false;} else if (choice == "F") {// Ask for the name of an employeevar name = PromptForString("What name are you looking for? ");// Make a new variable to store the found employee, or null if not foundEmployee foundEmployee = database.FindOneEmployee(name);// If the foundEmployee is still null, nothing was foundif (foundEmployee == null) {Console.WriteLine("No match found");} else {// Otherwise print details of the found employeeConsole.WriteLine($"{foundEmployee.Name} is in department {foundEmployee.Department} and makes ${foundEmployee.Salary}");}} else if (choice == "S") {var employees = database.GetAllEmployees();// Loop through each employeeforeach(var employee in employees) {// And print detailsConsole.WriteLine($"{employee.Name} is in department {employee.Department} and makes ${employee.Salary}");}} else {// Make a new employee objectvar employee = new Employee();// Prompt for values and save them in the employee's propertiesemployee.Name = PromptForString("What is your name? ");employee.Department = PromptForInteger("What is your department number? ");employee.Salary = PromptForInteger("What is your yearly salary (in dollars)? ");// Add it to the listdatabase.AddEmployee(employee);}// end of the `while` statement}}}}