This article demonstrates how to use multi-threading to return the name of two customers who have the closest birthdate. Also, it includes how to create API to add/retrieve customer details from SQL database using tasks and how to use MVC to call an API to add a new customer.
The proposed algorithm
- For each customer, find the difference between the selected customer and the rest of the customers.
- Do the same for all other customers. Note that you don’t have to look for the differences if it was already calculated. See the diagram below.
The complexity for calculating the diff between n customers will be equal to
n2-n-((n2-n)/2)
To find the closest birthday between 10 customers, you need to calculate 45 operations.
See below
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | |
| 0 | 0,1 | 0,2 | 0,3 | 0,4 | 0,5 | 0,6 | 0,7 | 0,8 | 0,9 | |
| 1 | 1,2 | 1,3 | 1,4 | 1,5 | 1,6 | 1,7 | 1,8 | 1,9 | ||
| 2 | 2,3 | 2,4 | 2,5 | 2,6 | 2,7 | 2,8 | 2,9 | |||
| 3 | 3,4 | 3,5 | 3,6 | 3,7 | 3,8 | 3,9 | ||||
| 4 | 4,5 | 4,6 | 4,7 | 4,8 | 4,9 | |||||
| 5 | 5,6 | 5,7 | 5,8 | 5,9 | ||||||
| 6 | 6,7 | 6,8 | 6,9 | |||||||
| 7 | 7,8 | 7,9 | ||||||||
| 8 | 8,9 | |||||||||
| 9 |
The main idea is to find the difference between n customers using multi-threading where each task will return the minimum difference between one customer and the rest of the customers. The tasks will be executed asynchronously on a separate processor. Each task will return an object that will include the customer index in the array, the index of the customer with minimum difference, and the difference value.
The last step is to find the objects that have the minimum difference from all the returned task objects. The resulted object will include the index of the first customer and the index of the second customer with closest birthdates.
The project is created using Visual Studio 2015 and MVC5
Create an SQL database with one table using the following script.
- CREATE DATABASE [CustomersDB]
- GO
- SET ANSI_NULLS ON
- GO
- SET QUOTED_IDENTIFIER ON
- GO
- CREATE TABLE [dbo].[PersonalInformation](
- [ID] [uniqueidentifier] NOT NULL CONSTRAINT [DF_PersonalInformation_ID]
- DEFAULT (newid()),
- [FirstName] [nvarchar](50) NULL,
- [LastName] [nvarchar](50) NULL,
- [BirthDate] [datetime] NULL
- ) ON [PRIMARY]
- GO

Create a new MVC5 project using Visual Studio 2015.

Under Controller folder, add a new API called CustomerApiController, allow the user to add a new customer to the database, retrieve all customer IDs, and retrieve each customer's details.

- The API controller code is as below.
- public class CustomerApiController : ApiController
- {
- [HttpPost]
- public IHttpActionResult AddClient(Customer customer)
- {
- Repository.AddCustomers(customer);
- return Ok(customer);
- }
- [HttpGet]
- [ActionName("GetCustomer")]
- [ResponseType(typeof(Customer))]
- public IHttpActionResult GetCustomer(Guid id)
- {
- return Ok(Repository.CustomerInfo(id));
- }
- [HttpGet]
- [ActionName("CustomersOId")]
- public IEnumerable<Guid> CustomersOId()
- {
- return Repository.CustomersOID();
- }
- }
2- Need to create the model part to enable connecting to the SQL. Under the Models folder, create the Repository.cs files.

... which include retrieving and adding data to the customer database tables.
Note
You can use any ORM Model but this is not part of this article.
- The Repository code is,
- public static class Repository
- {
- /// <summary>
- /// Add customer to the customer table
- /// </summary>
- /// <param name="customer"></param>
- public static void AddCustomers(Customer customer)
- {
- string sql = "INSERT INTO PersonalInformation(FirstName,LastName,BirthDate)
- VALUES(@FirstName,@LastName,@BirthDate)";
- using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["CustomerConnection"].ToString()))
- {
- connection.Open();
- using (SqlTransaction transaction = connection.BeginTransaction())
- {
- using (SqlCommand command = new SqlCommand(sql, connection, transaction))
- {
- command.CommandType = CommandType.Text;
- command.Parameters.AddWithValue("@FirstName", customer.FirstName);
- command.Parameters.AddWithValue("@LastName", customer.LastName);
- command.Parameters.AddWithValue("@BirthDate", customer.BirthDate);
- command.ExecuteNonQuery();
- transaction.Commit();
- }
- }
- }
- }
- /// Get All Customers OID’s
- public static List<Guid> CustomersOID()
- {
- string sql = "SELECT ID from PersonalInformation";
- List<Guid> customerOIds = new List<Guid>();
- using (SqlConnection connection =
- new SqlConnection(ConfigurationManager.ConnectionStrings["CustomerConnection"].ToString()))
- {
- connection.Open();
- using (SqlCommand sqlCommand = new SqlCommand(sql, connection))
- {
- using (SqlDataReader reader = sqlCommand.ExecuteReader())
- {
- while (reader.Read())
- {
- Guid guid = reader.GetGuid(0);
- customerOIds.Add(guid);
- }
- }
- }
- }
- return customerOIds;
- }
- /// Get Customer detail once we pass the guid
- public static Customer CustomerInfo(Guid guid)
- {
- string sql = "SELECT FirstName,LastName,BirthDate from PersonalInformation where ID =@ID";
- Customer C1 = new Customer();
- using (SqlConnection connection =new SqlConnection(ConfigurationManager.ConnectionStrings["CustomerConnection"].ToString()))
- {
- connection.Open();
- using (SqlCommand sqlCommand = new SqlCommand(sql, connection))
- {
- sqlCommand.Parameters.Add(new SqlParameter("@ID", SqlDbType.UniqueIdentifier)).Value = guid;
- using (SqlDataReader reader = sqlCommand.ExecuteReader())
- {
- while (reader.Read())
- {
- C1.FirstName = reader.GetString(0);
- C1.LastName= reader.GetString(1);
- C1.BirthDate = reader.GetDateTime(2);
- }
- }
- }
- }
- return C1;
- }
- }
- Create the Customer.cs file that defines the customer object ( you can create the file under Model folder).
- public class Customer
- {
- public Guid ID { get; set; }
- public string FirstName { get; set; }
- public string LastName { get; set; }
- public DateTime BirthDate { get; set; }
- }
Build the algorithm of finding the closest birthdates using multi-threading. You can create a new folder to add the classes needed to find the closest birthdates or for simplicity, I have added the 2 required classes for the algorithm DiffClass and Resultstruct under Models folder.





Join the conversation! Your thoughts help the community grow.