Missing Document Title
theme: Next, 1
Using C# Classes to Create a Database
- Using classes and List we will create an employee database
- Database will be able to
- Create
- Read
- Update
- Delete
Reviewing the starting code.
We will make a new project: dotnet new sdg-console -o SuncoastHumanResources
Starting code
- Defines an
Employee
class and contains code to input the details of a single employee.
You can use
sdg warp SuncoastHumanResources
to download this code (after you cd
into the project)
[.autoscale: true]
[.column]
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;}
[.column]
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.");}}}
Lacks features
- Good start
- Cannot store more than one employee
- Lacks menu
- Cannot search, update, or delete employees
Adding a List
to store our employees
The List
we will create will look like this:
var employees = new List<Employee>();
- Naming variables is important
employees
is a hint that the variable is a collection. The convention we follow for collections is to use pluralized names.
Adding a feature to add an employee
After the input we'll add code to add the employee to a list
employees.Add(employee);
Make a simple menu
// 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}
[fit] Add an option to show all the employees
To work on the R
ead part of the application we'll add an option to read all of the employees.
This is often the next simplest feature of the code to write since we only need to "loop" and "print".
Update the menu
Console.Write("What do you want to do? (A)dd an employee or (S)how all the employees or (Q)uit: ");
Add an else if
to our menu choices
if (choice == "Q") {// They said quit, so set our keepGoing to falsekeepGoing = false;} else if (choice == "S") {
Add the code to show all of the employees
// Loop through each employeeforeach(var employee in employees) {// And print details (split on two lines for the slide)Console.WriteLine($"{employee.Name} is in department " +"{employee.Department} and makes ${employee.Salary}");}
Find an employee by name
The other part of R
eading from the database is to search for a specific item.
We will add an option to find a specific employee by matching the name.
Algorithm
- Create a variable named
foundEmployee
- Prompt for the name
- Loop through the list to look for a match
- If we find one, update
foundEmployee
- If we find one, update
- After the loop,
foundEmployee
is eithernull
(not found) or refers to the matching item - Show a message if
null
, otherwise show the details.
Update the menu
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: ");
Update the else if
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}");}
Improving this code by adding LINQ
- While this code works it is "tedious"
- We can leverage
LINQ
here. - Then we can utilize
FirstOrDefault
for searching
// 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 and Update
Exercise for the reader...
Refactoring the code
- Functions for adding, searching, and displaying all exist in the main code.
- Extracting code into a specific class will increase the code's clarity and give specific places to implement new features.
Classes and methods should do ONE thing, and ONE thing well
[fit] Our Main
does too much
[fit] Allow Main
to be our User Interface
[fit] Make a class EmployeeDatabase to deal with the List
[.autoscale: true]
API
- Create a class
EmployeeDatabase
- Move our
List<Employee>
inside. - Make this class property private
- Develop public methods to perform the common actions we need:
GetAllEmployees
,FindOneEmployee
,AddEmployee
. - Methods receives data it needs and returns the data it provides.
- These methods essentially create an API (Application Programming Interface) for how to use this code.
What does isolated code provide?
- 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.
- As long as the inputs/outputs stay the same (or change only slightly) we are more free to change the implementation
- This is called decoupling
class EmployeeDatabase{// Keep a *private* copy of the employee list.private List<Employee> employees = new List<Employee>();// Get a list of all the employeespublic List<Employee> GetAllEmployees(){return employees;}// Add an employee to the list of employees we are managing.public void AddEmployee(Employee newEmployee){employees.Add(newEmployee);}// 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;}}