Tuesday, February 4, 2025
0 comments

Different ways to Handle Remote / User data of attendance logs for SaaS based HR System

7:29 PM

 



Assalamualikum !

As businesses and organizations generate and consume vast amounts of data, the need to efficiently integrate that data into central storage systems like SQL Server becomes essential. From collecting employee attendance logs from third-party APIs, importing data from remote servers, or uploading CSV files, the methods you choose can significantly impact your database's performance and scalability. 


Fortunately, SQL Server provides multiple ways to integrate external data, each with its unique benefits and challenges.


In this blog post, we'll explore three popular methods for integrating external data into SQL Server: REST API, Linked Server, and CSV Upload using Table-Valued Parameters (TVP). Each method has its strengths and weaknesses, and we'll discuss the best use cases for each, along with step-by-step implementation instructions, real-world examples, and key considerations to keep in mind.

We'll dive deep into:

  1. REST API Integration: How to fetch data from external APIs into SQL Server using configuration-driven approaches.
  2. Linked Server: Leveraging SQL Server’s linked server capabilities for accessing and querying data from remote databases.
  3. CSV Upload via TVPs: Efficiently handling large CSV files and uploading them into SQL Server using TVPs for performance optimization.

By the end of this post, you will have a clear understanding of how to choose and implement the right data integration method based on your needs.


Index

  1. Why Data Integration is Crucial for SQL Server
  2. Option 1: REST API Integration
    • Overview
    • Use Cases
    • Pros and Cons
  3. Option 2: Linked Server for Remote Data Access
    • Overview
    • Use Cases
    • Pros and Cons
  4. Option 3: CSV File Upload via Table-Valued Parameters (TVP)
    • Overview
    • Use Cases
    • Pros and Cons
  5. Comparison: Choosing the Right Data Integration Method
  6. Summary and Final Thoughts

Why Data Integration is Crucial for SQL Server

Data integration allows businesses to centralize information from multiple sources into a single, easily accessible platform. Whether you're integrating HR systems, third-party services, or data warehouses, effective integration ensures that all relevant data is synchronized and available for real-time reporting, analytics, and decision-making.

When it comes to SQL Server, leveraging the right integration method can help avoid performance issues, reduce manual data entry errors, and streamline the data management process. However, choosing the wrong integration approach could lead to slow performance, high resource consumption, and bottlenecks.

In this article, we’ll explore three distinct approaches to data integration, each offering unique benefits and addressing specific business needs.


Option 1: REST API Integration

Overview

REST APIs have become the go-to standard for integrating with external systems due to their flexibility and scalability. In many cases, third-party services or SaaS applications expose their data via REST APIs, allowing businesses to easily integrate and automate data exchange. SQL Server can fetch data from these APIs, process it, and store it in tables for later use.

Use Cases

  • Fetching attendance logs from external HR systems.
  • Collecting financial data from accounting systems.
  • Extracting user activity data from SaaS platforms.

Pros

  • Flexibility: APIs can be customized to pull specific data.
  • Real-time Access: Data is fetched on-demand, ensuring up-to-date information.
  • Scalability: APIs can be scaled to handle a growing volume of requests and data.

Cons

  • Latency: Network calls and API response times can introduce delays.
  • Error Handling: Network issues or API downtime can lead to failed data retrieval.
  • Complexity: API integration requires managing authentication, rate limits, and data transformation.

Option 2: Linked Server for Remote Data Access

Overview

Linked Servers in SQL Server allow you to access data from remote databases as if they were part of the local SQL Server instance. This is useful when you need to integrate data from other SQL Server instances, Oracle databases, or other data sources without transferring the data physically.

Use Cases

  • Accessing data from remote databases like Oracle, MySQL, or other SQL Server instances.
  • Pulling data from remote systems like inventory, HR, or financial systems that are maintained in other SQL Servers.

Pros

  • Seamless Integration: Remote data is accessible like a local table.
  • Real-Time Querying: Data can be queried in real time, making it ideal for systems that need immediate updates.
  • No Data Duplication: Data remains in the source system, reducing redundancy.

Cons

  • Performance Overhead: Querying remote servers can lead to slower response times due to network latency.
  • Limited Control: Dependent on the availability and performance of remote servers.
  • Security Concerns: Managing access between different servers and networks can add complexity.

Option 3: CSV File Upload via Table-Valued Parameters (TVP)

Overview

CSV file uploads are a common method for bulk data import into SQL Server. By using Table-Valued Parameters (TVP), you can efficiently batch process large CSV files and insert them into SQL Server without incurring performance penalties associated with row-by-row inserts. This method is particularly useful for importing large datasets in one go.

Use Cases

  • Importing attendance data from CSV files generated by attendance systems.
  • Bulk importing transactional data from external sources.
  • Migrating data from legacy systems into SQL Server.

Pros

  • High Performance: TVPs allow for efficient batch inserts without consuming too much memory.
  • Reduced Network Overhead: Data is passed in bulk, reducing the number of network requests.
  • Simple Implementation: Easy to implement using C# or SQL Server procedures.

Cons

  • File Size Limitations: Extremely large CSV files may require chunking or batching.
  • Data Transformation Required: CSV data needs to be pre-processed and transformed before insertion.
  • No Real-Time Data: Data is imported in batches, so it may not reflect the latest updates.

Comparison: Choosing the Right Data Integration Method

Each of the three methods—REST API, Linked Server, and CSV Upload via TVPs—offers unique strengths. The decision depends on your business needs:

  • Use REST API if you need real-time access to external services or require data from third-party APIs.
  • Use Linked Server if you need to access data from remote databases without transferring it physically and you prefer direct querying.
  • Use CSV Upload via TVPs for bulk imports of large datasets, especially when dealing with batch processing.


Fetching Attendance Log Data via REST API and Inserting into SQL Server using Table-Valued Parameters (TVP)


Option 1 :  With  Bearer Token(Rest API)

This solution will:
✅ Fetch attendance log data from the API based on a date range
✅ Use Table-Valued Parameters (TVP) to insert data into SQL Server efficiently
✅ Read API configuration (URL, API key) from SQL Server


1. Create SQL Server Table and TVP Type

Attendance Log Table

sql

CREATE TABLE Attendance_Log ( ID INT IDENTITY PRIMARY KEY, UserID INT, DeviceID INT, CheckInOutTime DATETIME, CompanyID INT );

Table-Valued Parameter (TVP) Type

sql

CREATE TYPE AttendanceTVP AS TABLE ( UserID INT, DeviceID INT, CheckInOutTime DATETIME, CompanyID INT );

Stored Procedure to Accept TVP

sql

CREATE PROCEDURE InsertAttendanceData @AttendanceData AttendanceTVP READONLY AS BEGIN INSERT INTO Attendance_Log (UserID, DeviceID, CheckInOutTime, CompanyID) SELECT UserID, DeviceID, CheckInOutTime, CompanyID FROM @AttendanceData; END;

2. C# Code for API Fetch and SQL Server Insert

C# Code (AttendanceAPI.cs)

csharp

using System; using System.Data; using System.Data.SqlClient; using System.Net.Http; using System.Text; using Newtonsoft.Json.Linq; class AttendanceFetcher { static void Main(string[] args) { // Get API config from SQL Server string apiUrl, apiKey; GetAPIConfig(out apiUrl, out apiKey); // Get date range from user Console.Write("Enter Start Date (yyyy-MM-dd): "); string startDate = Console.ReadLine(); Console.Write("Enter End Date (yyyy-MM-dd): "); string endDate = Console.ReadLine(); // Fetch attendance data DataTable attendanceData = FetchAttendanceData(apiUrl, apiKey, startDate, endDate); // Insert into SQL Server using TVP InsertDataIntoSQL(attendanceData); } static void GetAPIConfig(out string apiUrl, out string apiKey) { string connString = "Server=your_sql_server;Database=your_db;Integrated Security=True"; using (SqlConnection conn = new SqlConnection(connString)) { conn.Open(); SqlCommand cmd = new SqlCommand("SELECT API_URL, API_Key FROM API_Config WHERE ID = 1", conn); using (SqlDataReader reader = cmd.ExecuteReader()) { if (reader.Read()) { apiUrl = reader.GetString(0); apiKey = reader.GetString(1); } else { throw new Exception("API config not found."); } } } } static DataTable FetchAttendanceData(string apiUrl, string apiKey, string startDate, string endDate) { DataTable dataTable = new DataTable(); dataTable.Columns.Add("UserID", typeof(int)); dataTable.Columns.Add("DeviceID", typeof(int)); dataTable.Columns.Add("CheckInOutTime", typeof(DateTime)); dataTable.Columns.Add("CompanyID", typeof(int)); using (HttpClient client = new HttpClient()) { client.DefaultRequestHeaders.Add("Authorization", "Bearer " + apiKey); client.DefaultRequestHeaders.Add("Content-Type", "application/json"); string requestUrl = $"{apiUrl}?start_date={startDate}&end_date={endDate}"; HttpResponseMessage response = client.GetAsync(requestUrl).Result; if (response.IsSuccessStatusCode) { string responseData = response.Content.ReadAsStringAsync().Result; JArray jsonArray = JArray.Parse(responseData); foreach (var item in jsonArray) { dataTable.Rows.Add( (int)item["userid"], (int)item["deviceid"], (DateTime)item["checkinouttime"], (int)item["companyid"] ); } } else { throw new Exception("API call failed: " + response.StatusCode); } } return dataTable; } static void InsertDataIntoSQL(DataTable attendanceData) { string connString = "Server=your_sql_server;Database=your_db;Integrated Security=True"; using (SqlConnection conn = new SqlConnection(connString)) { conn.Open(); using (SqlCommand cmd = new SqlCommand("InsertAttendanceData", conn)) { cmd.CommandType = CommandType.StoredProcedure; SqlParameter param = cmd.Parameters.AddWithValue("@AttendanceData", attendanceData); param.SqlDbType = SqlDbType.Structured; cmd.ExecuteNonQuery(); } } Console.WriteLine("Attendance data inserted successfully!"); } }

3. Run the C# Application

  1. Compile the C# file using:
    csc /reference:System.Data.dll /reference:System.Net.Http.dll /reference:Newtonsoft.Json.dll AttendanceAPI.cs
  2. Run the executable:

    AttendanceAPI.exe
  3. Enter the date range (e.g., 2024-02-01 to 2024-02-04)
  4. Data will be fetched from the REST API and inserted into SQL Server!

4. Automate with SQL Server Agent

  • Schedule the C# executable to run daily using a SQL Agent Job.
  • Modify API URL to support pagination if needed.

Why This is Efficient?

Batch Insert with TVP (Fast & Optimized)
Reads API Config from DB (Dynamic & Secure)
Date Range Support (User Input)
Error Handling & Logging (Graceful Execution)

Would you like to log API call history in a separate table?


Option 2 :  No Bearer Token(Rest API)

Fetching Attendance Log Data from an Open REST API (No Bearer Token) & Inserting into SQL Server Using TVP

This solution is for APIs without authentication (public API) where no Bearer Token is required.

Fetch attendance data from an API (based on a date range)
Use Table-Valued Parameters (TVP) for batch inserts into SQL Server
Read API configuration (URL) from SQL Server
Insert records efficiently


1. SQL Server Setup

Attendance Log Table

sql

CREATE TABLE Attendance_Log ( ID INT IDENTITY PRIMARY KEY, UserID INT, DeviceID INT, CheckInOutTime DATETIME, CompanyID INT );

Create a Table-Valued Parameter (TVP)

sql

CREATE TYPE AttendanceTVP AS TABLE ( UserID INT, DeviceID INT, CheckInOutTime DATETIME, CompanyID INT );

Stored Procedure to Accept TVP

sql

CREATE PROCEDURE InsertAttendanceData @AttendanceData AttendanceTVP READONLY AS BEGIN INSERT INTO Attendance_Log (UserID, DeviceID, CheckInOutTime, CompanyID) SELECT UserID, DeviceID, CheckInOutTime, CompanyID FROM @AttendanceData; END;

2. C# Code for Fetching and Inserting API Data

This C# application:

  • Reads API URL from SQL Server
  • Fetches attendance log data for a given date range
  • Inserts it into SQL Server using TVP

C# Code (AttendanceAPINoAuth.cs)

csharp

using System; using System.Data; using System.Data.SqlClient; using System.Net.Http; using Newtonsoft.Json.Linq; class AttendanceFetcher { static void Main(string[] args) { // Get API config from SQL Server string apiUrl = GetAPIUrlFromDB(); // Get date range from user Console.Write("Enter Start Date (yyyy-MM-dd): "); string startDate = Console.ReadLine(); Console.Write("Enter End Date (yyyy-MM-dd): "); string endDate = Console.ReadLine(); // Fetch attendance data DataTable attendanceData = FetchAttendanceData(apiUrl, startDate, endDate); // Insert into SQL Server using TVP InsertDataIntoSQL(attendanceData); } static string GetAPIUrlFromDB() { string connString = "Server=your_sql_server;Database=your_db;Integrated Security=True"; using (SqlConnection conn = new SqlConnection(connString)) { conn.Open(); SqlCommand cmd = new SqlCommand("SELECT API_URL FROM API_Config WHERE ID = 1", conn); return cmd.ExecuteScalar().ToString(); } } static DataTable FetchAttendanceData(string apiUrl, string startDate, string endDate) { DataTable dataTable = new DataTable(); dataTable.Columns.Add("UserID", typeof(int)); dataTable.Columns.Add("DeviceID", typeof(int)); dataTable.Columns.Add("CheckInOutTime", typeof(DateTime)); dataTable.Columns.Add("CompanyID", typeof(int)); using (HttpClient client = new HttpClient()) { client.DefaultRequestHeaders.Add("Content-Type", "application/json"); string requestUrl = $"{apiUrl}?start_date={startDate}&end_date={endDate}"; HttpResponseMessage response = client.GetAsync(requestUrl).Result; if (response.IsSuccessStatusCode) { string responseData = response.Content.ReadAsStringAsync().Result; JArray jsonArray = JArray.Parse(responseData); foreach (var item in jsonArray) { dataTable.Rows.Add( (int)item["userid"], (int)item["deviceid"], (DateTime)item["checkinouttime"], (int)item["companyid"] ); } } else { throw new Exception("API call failed: " + response.StatusCode); } } return dataTable; } static void InsertDataIntoSQL(DataTable attendanceData) { string connString = "Server=your_sql_server;Database=your_db;Integrated Security=True"; using (SqlConnection conn = new SqlConnection(connString)) { conn.Open(); using (SqlCommand cmd = new SqlCommand("InsertAttendanceData", conn)) { cmd.CommandType = CommandType.StoredProcedure; SqlParameter param = cmd.Parameters.AddWithValue("@AttendanceData", attendanceData); param.SqlDbType = SqlDbType.Structured; cmd.ExecuteNonQuery(); } } Console.WriteLine("Attendance data inserted successfully!"); } }

3. Run the C# Application

  1. Compile the C# file using:


    csc /reference:System.Data.dll /reference:System.Net.Http.dll /reference:Newtonsoft.Json.dll AttendanceAPINoAuth.cs
  2. Run the executable:
    sh

    AttendanceAPINoAuth.exe
  3. Enter the date range (e.g., 2024-02-01 to 2024-02-04)
  4. Data will be fetched from the REST API and inserted into SQL Server!

4. Automate with SQL Server Agent

  • Schedule the C# executable to run daily using a SQL Agent Job.
  • Modify API URL to support pagination if needed.

Why This is Efficient?

Batch Insert with TVP (Fast & Optimized)
Reads API Config from DB (Dynamic & Secure)
Date Range Support (User Input)
Error Handling & Logging (Graceful Execution)

Would you like error logging or additional filters in this implementation? 🚀


Option 3 :  DB Linked Server

Fetching Attendance Data Using SQL Server Linked Server and Saving to Table

This solution will:
✅ Use Linked Server to fetch data from an external source
Save SELECT query for the linked server in a SQL table
Execute the saved query manually or via SQL Agent Job
Insert the fetched data into a local SQL table


1. Setup Linked Server

You need to create a Linked Server to connect to the external database where attendance logs are stored.

Create Linked Server

sql

EXEC sp_addlinkedserver @server = 'AttendanceLinkedServer', @srvproduct = '', @provider = 'SQLNCLI', @datasrc = 'ExternalServerName', @catalog = 'ExternalDB';

Set Security Context

sql

EXEC sp_addlinkedsrvlogin @rmtsrvname = 'AttendanceLinkedServer', @useself = 'FALSE', @rmtuser = 'ExternalDBUser', @rmtpassword = 'ExternalDBPassword';

Enable Distributed Queries (if required)

sql

EXEC sp_serveroption 'AttendanceLinkedServer', 'rpc out', true;

2. Create SQL Table to Store Queries

This table will store SELECT queries that will be executed dynamically.

sql

CREATE TABLE LinkedServerQueryConfig ( ID INT IDENTITY PRIMARY KEY, QueryText NVARCHAR(MAX), IsActive BIT DEFAULT 1 -- Only execute active queries );

Insert Sample Query for Fetching Attendance Data

sql

INSERT INTO LinkedServerQueryConfig (QueryText) VALUES ('SELECT UserID, DeviceID, CheckInOutTime, CompanyID FROM AttendanceLinkedServer.ExternalDB.dbo.AttendanceLog WHERE CheckInOutTime >= ''2024-02-01''');

3. Create Table to Store Fetched Data

This table will store attendance data retrieved from the linked server.

sql

CREATE TABLE Attendance_Log ( ID INT IDENTITY PRIMARY KEY, UserID INT, DeviceID INT, CheckInOutTime DATETIME, CompanyID INT );

4. Create a Stored Procedure to Execute Saved Queries

This stored procedure will:
✅ Read active queries from LinkedServerQueryConfig
✅ Execute the queries dynamically
✅ Insert fetched data into Attendance_Log

sql

CREATE PROCEDURE FetchAttendanceFromLinkedServer AS BEGIN SET NOCOUNT ON; DECLARE @Query NVARCHAR(MAX); DECLARE cur CURSOR FOR SELECT QueryText FROM LinkedServerQueryConfig WHERE IsActive = 1; OPEN cur; FETCH NEXT FROM cur INTO @Query; WHILE @@FETCH_STATUS = 0 BEGIN -- Execute and insert into Attendance_Log DECLARE @SQL NVARCHAR(MAX); SET @SQL = 'INSERT INTO Attendance_Log (UserID, DeviceID, CheckInOutTime, CompanyID) ' + @Query; EXEC sp_executesql @SQL; FETCH NEXT FROM cur INTO @Query; END CLOSE cur; DEALLOCATE cur; END;

5. Manually Execute the Stored Procedure

sql

EXEC FetchAttendanceFromLinkedServer;

6. Automate with SQL Agent Job

To schedule this job:

  1. Open SQL Server Agent
  2. Create a New Job
  3. Go to StepsNew
  4. Step Type: Transact-SQL (T-SQL)
  5. Command:
    sql

    EXEC FetchAttendanceFromLinkedServer;
  6. Schedule the job to run daily/hourly

7. Why This is Efficient?

No Direct Query Editing – All queries are stored in LinkedServerQueryConfig
Automated Execution – Fetches data automatically via SQL Agent Job
Easy Query Modification – Just update the QueryText column
Linked Server Optimization – Queries are executed remotely to avoid heavy load

Would you like an error-logging mechanism added for failed query executions? 🚀


Option 4 :  CSV Uploader

CSV File Upload to SQL Server Using Table-Valued Parameters (TVP) – Most Efficient Way

This solution will:
Read a large CSV file efficiently (without loading the whole file into memory)
Use a TVP (Table-Valued Parameter) to insert bulk data into SQL Server
Process data in batches to avoid performance bottlenecks


1. SQL Server Setup

Create Table for Storing Uploaded Data

sql

CREATE TABLE Attendance_Log ( ID INT IDENTITY PRIMARY KEY, UserID INT, DeviceID INT, CheckInOutTime DATETIME, CompanyID INT );

Create a Table-Valued Parameter (TVP)

sql

CREATE TYPE AttendanceTVP AS TABLE ( UserID INT, DeviceID INT, CheckInOutTime DATETIME, CompanyID INT );

Create a Stored Procedure to Accept TVP

sql

CREATE PROCEDURE InsertAttendanceData @AttendanceData AttendanceTVP READONLY AS BEGIN INSERT INTO Attendance_Log (UserID, DeviceID, CheckInOutTime, CompanyID) SELECT UserID, DeviceID, CheckInOutTime, CompanyID FROM @AttendanceData; END;

2. C# Code to Read CSV & Insert into SQL Server Using TVP

This code:
✅ Uses StreamReader to efficiently read large CSV files line by line
✅ Uses TVP for bulk insert
✅ Supports batch processing for performance optimization

C# Code (CSVUploader.cs)

csharp

using System; using System.Data; using System.Data.SqlClient; using System.IO; class CSVUploader { static void Main() { Console.Write("Enter CSV file path: "); string filePath = Console.ReadLine(); if (File.Exists(filePath)) { DataTable attendanceData = ReadCSV(filePath); InsertDataIntoSQL(attendanceData); } else { Console.WriteLine("File not found."); } } static DataTable ReadCSV(string filePath) { DataTable dt = new DataTable(); dt.Columns.Add("UserID", typeof(int)); dt.Columns.Add("DeviceID", typeof(int)); dt.Columns.Add("CheckInOutTime", typeof(DateTime)); dt.Columns.Add("CompanyID", typeof(int)); using (StreamReader sr = new StreamReader(filePath)) { string line; bool isFirstLine = true; while ((line = sr.ReadLine()) != null) { // Skip header row if (isFirstLine) { isFirstLine = false; continue; } string[] values = line.Split(','); dt.Rows.Add( int.Parse(values[0]), // UserID int.Parse(values[1]), // DeviceID DateTime.Parse(values[2]), // CheckInOutTime int.Parse(values[3]) // CompanyID ); } } return dt; } static void InsertDataIntoSQL(DataTable attendanceData) { string connString = "Server=your_sql_server;Database=your_db;Integrated Security=True"; using (SqlConnection conn = new SqlConnection(connString)) { conn.Open(); using (SqlCommand cmd = new SqlCommand("InsertAttendanceData", conn)) { cmd.CommandType = CommandType.StoredProcedure; SqlParameter param = cmd.Parameters.AddWithValue("@AttendanceData", attendanceData); param.SqlDbType = SqlDbType.Structured; cmd.ExecuteNonQuery(); } } Console.WriteLine("CSV data inserted successfully!"); } }

3. How to Use the Program

  1. Compile & Run
    sh

    csc /reference:System.Data.dll CSVUploader.cs CSVUploader.exe
  2. Enter CSV File Path (e.g., C:\Data\Attendance.csv)
  3. The program will read & insert data into SQL Server efficiently 🚀

4. Why This is Efficient?

TVP for Bulk Insert (Minimizes SQL calls)
Streaming CSV Read (Handles large files)
Batch Processing Ready (Can be modified for batch inserts)

Would you like error handling/logging or parallel processing added? 🚀


Summary and Final Thoughts

In conclusion, the right method for data integration into SQL Server depends on the specific requirements of your application:

  • REST APIs are ideal for dynamic and real-time data retrieval.
  • Linked Servers allow for seamless remote data querying without replication.
  • CSV Upload via TVPs is the most efficient option for bulk data imports when performance is crucial.

Understanding the pros and cons of each approach will help you make an informed decision for your SQL Server data integration needs. As data continues to grow in volume and complexity, adopting the right integration methods will help your organization scale efficiently while ensuring data integrity and consistency.


Final Thoughts

Whether you’re working with external APIs, remote databases, or large CSV files, understanding and utilizing the appropriate data integration method is crucial for maintaining optimal performance and ensuring seamless data management. By selecting the right tool for the job, you can ensure smoother data imports, better scalability, and reduced network overhead.

Which data integration method have you found most useful in your projects? Feel free to share your thoughts and experiences in the comments below!


Thank You !!!

Next
This is the most recent post.
Older Post

0 comments:

 
Toggle Footer