This project was created as part of my Visual Programming class (Jan 2023) where I created a three-layer application in C# and .NET Framework to help small resorts manage their booking.
C#.NET Framework 4.8Windows FormsDependency InjectionRegexThree Layer applicationLocalDBUnit tests
This is a 3-layer app consisting of a Data Layer that communicates with our database made using Microsoft SQL LocalDB. Inside the data layer, there are repositories containing all the necessary methods for basic CRUD operations with a database. On the Business layer, I've implemented logic for those operations and passed them onto the Presentation Layer. The presentation Layer is made of several Windows forms used for managing client, accommodation, and reservation data. Apart from three-layer architecture, this app uses Dependency Injection for separation of concerns and Regex to make sure users are entering valid data into textboxes. On the Reservation form, there are several methods to make sure that you can't create a reservation for already used accommodation and also methods to display the total cost of renting accommodation for a selected period.
๐ป Code Examples:
Data Layer
public int InsertClient(Client client)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
string query = "INSERT INTO CLIENTS (first_name,last_name,phone_number,email) VALUES(@firstName,@lastName,@phoneNumber,@email)";
SqlCommand command = new SqlCommand(query, connection);
command.Parameters.AddWithValue("@firstName", client.FirstName);
command.Parameters.AddWithValue("@lastName", client.LastName);
command.Parameters.AddWithValue("@phoneNumber", client.PhoneNumber);
command.Parameters.AddWithValue("@email", client.Email);
connection.Open();
int rowsUpdated;
rowsUpdated = command.ExecuteNonQuery();
connection.Close();
return rowsUpdated;
}
}Business Layer
public string InsertClient(Client client)
{
int rowsAffected = this.clientrepository.InsertClient(client);
if (rowsAffected > 0)
{
return "Client successfully added!";
}
else
{
return "Failed to insert client!";
}
}Presentation Layer
private void button_InsertClient_Click(object sender, EventArgs e)
{
if (textBox_FirstName.Text == "" || textBox_LastName.Text == "" ||
textBox_PhoneNumber.Text == "" ||
textBox_Email.Text == "")
{
MessageBox.Show("You have to fill out all of the fields", "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
textBox_FirstName.Focus();
return;
}
else if (!Regex.Match(textBox_Email.Text, @"^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$").Success)
{
MessageBox.Show("E-mail entered incorrectly!", "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
textBox_Email.Focus();
return;
}
else if (!Regex.Match(textBox_FirstName.Text, @"^[A-Z]+[A-Za-z\s]{1,15}([A-Z]?)+([A-Za-z\s]?)$").Success)
{
MessageBox.Show("First name cannot contain a digit!", "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
textBox_FirstName.Focus();
return;
}
else if (!Regex.Match(textBox_LastName.Text, @"^[A-Z]+[A-Za-z\s-]{1,30}([A-Z]?)+([A-Za-z\s]?)$").Success)
{
MessageBox.Show("Last name cannot contain a digit!", "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
textBox_LastName.Focus();
return;
}
else if (!Regex.Match(textBox_PhoneNumber.Text, @"^[0][6]\d{7,8}$").Success)
{
MessageBox.Show("Phone number entered incorrectly!", "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
textBox_PhoneNumber.Focus();
return;
}
else
{
Client client = new Client();
client.FirstName = textBox_FirstName.Text;
client.LastName = textBox_LastName.Text;
client.PhoneNumber = textBox_PhoneNumber.Text;
client.Email = textBox_Email.Text;
string result = clientBusiness.InsertClient(client);
MessageBox.Show(result, "Message", MessageBoxButtons.OK, MessageBoxIcon.Information);
textBox_FirstName.Text = "";
textBox_LastName.Text = "";
textBox_PhoneNumber.Text = "";
textBox_Email.Text = "";
}
} As part of my Software Quality Management class in my Master's studies, I added several unit tests to make sure key parts of this app are working correctly. Below you can find examples of two Unit tests. The former is for checking if a valid administrator exists in a database and the latter is created to make sure you can successfully insert new clients into the database.
Unit test 1
[TestFixture]
public class DeleteAccommodationTest
{
private readonly IAdminRepository adminRepository;
public DeleteAccommodationTest()
{
// Assuming Constants.ConnectionString is correctly configured for testing purposes
adminRepository = new AdminRepository();
}
[Test]
public void GetAdmin_WithValidCredentials_ShouldReturnAdmin()
{
// Arrange
string validUsername = "djordje";
string validPassword = "Adminadmin123!";
// Act
Admin result = adminRepository.GetAdmin(validUsername, validPassword);
// Assert
Assert.IsNotNull(result);
Assert.AreEqual(validUsername, result.Username);
Assert.AreEqual(validPassword, result.Password);
}
[Test]
public void GetAdmin_WithInvalidCredentials_ShouldReturnEmptyAdmin()
{
// Arrange
string invalidUsername = "nonexistent";
string invalidPassword = "InvalidPassword";
// Act
Admin result = adminRepository.GetAdmin(invalidUsername, invalidPassword);
// Assert
Assert.IsNotNull(result);
Assert.AreEqual(0, result.Id); // Assuming Id is initialized as 0 for an empty admin
Assert.IsNull(result.Username);
Assert.IsNull(result.Password);
}
}Unit test 2
[TestFixture]
public class InsertClientTest
{
private readonly IClientRepository clientRepository;
public InsertClientTest()
{
// Assuming Constants.ConnectionString is correctly configured for testing purposes
clientRepository = new ClientRepository();
}
[Test]
public void InsertClient_ShouldReturnOneRowInserted()
{
// Arrange
Client newClient = new Client
{
FirstName = "John",
LastName = "Doe",
PhoneNumber = "123456789",
Email = "john.doe@example.com"
};
// Act
int rowsInserted = clientRepository.InsertClient(newClient);
// Assert
Assert.AreEqual(1, rowsInserted);
}
}





