Multi-layered .NET solution for fetching, processing, and synchronizing exchange rate data using staging tables and SQL MERGE
ExchangeRateSolution is a modular, layered .NET solution designed for working with exchange rate data. The project includes domain layer, data access layer, service layer, and Windows Service component.
- Fetch exchange rate data from external sources
- Write to staging tables for validation
- Safely transfer to main tables using MERGE
- Automated background data synchronization
- Maintainable layered architecture
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β ExchangeTransferWinService β
β (Windows Service - Timer) β
ββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββ
β
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β ExchangeRate.Service β
β (Business Logic) β
ββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββ
β
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β ExchangeRate.Data β
β (Repository Pattern) β
ββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββ
β
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β ExchangeRate.Core β
β (Domain Models & Interfaces) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- β Layered Architecture - Clean separation of concerns
- β Repository Pattern - Abstracted data access
- β Staging Tables - Safe data validation before merge
- β SQL MERGE - Automatic INSERT/UPDATE logic
- β Transaction Support - Rollback on errors
- β Bulk Operations - High-performance data transfer
- β Windows Service - Automated background processing
- β Testable - Dependency injection ready
ExchangeRateSolution/
β
βββ ExchangeRate.Core/ # Domain Layer
β βββ Entities/ # Domain models
β βββ Interfaces/ # Repository interfaces
β βββ DTOs/ # Data transfer objects
β
βββ ExchangeRate.Data/ # Data Access Layer
β βββ Repositories/ # Repository implementations
β βββ Context/ # Database context
β βββ Migrations/ # Database migrations
β
βββ ExchangeRate.Service/ # Service Layer
β βββ Services/ # Business logic
β βββ Validators/ # Data validation
β βββ Mappers/ # Object mapping
β
βββ ExchangeTransferWinService/ # Windows Service
βββ Worker.cs # Service worker
βββ App.config # Configuration
External API
β
[Fetch Rates]
β
ExchangeRate_Staging (Temp)
β
[Validation]
β
[SQL MERGE]
β
ExchangeRate (Main Table)
- .NET Framework 4.7.2+
- SQL Server 2016+
- Visual Studio 2019+
- Administrator privileges (for Windows Service)
-- Create main table
CREATE TABLE ExchangeRate (
Id INT PRIMARY KEY IDENTITY(1,1),
CurrencyCode NVARCHAR(3) NOT NULL,
Rate DECIMAL(18,6) NOT NULL,
RateDate DATE NOT NULL,
CreatedAt DATETIME NOT NULL DEFAULT GETDATE(),
UpdatedAt DATETIME,
CONSTRAINT UQ_Currency_Date UNIQUE (CurrencyCode, RateDate)
)
-- Create staging table
CREATE TABLE ExchangeRate_Staging (
Id INT PRIMARY KEY IDENTITY(1,1),
CurrencyCode NVARCHAR(3) NOT NULL,
Rate DECIMAL(18,6) NOT NULL,
RateDate DATE NOT NULL,
CreatedAt DATETIME NOT NULL DEFAULT GETDATE()
)
-- Service settings
CREATE TABLE ServiceSettings (
Id INT PRIMARY KEY IDENTITY(1,1),
IntervalMinutes INT NOT NULL,
IsActive BIT NOT NULL,
ApiUrl NVARCHAR(500)
)
INSERT INTO ServiceSettings VALUES (60, 1, 'https://api.exchangerate.com/rates')Edit App.config:
<connectionStrings>
<add name="ExchangeRateDb"
connectionString="Server=SERVER;Database=ExchangeRateDB;Integrated Security=true;" />
</connectionStrings>
<appSettings>
<add key="ApiUrl" value="https://api.exchangerate.com/rates" />
<add key="ApiKey" value="YOUR_API_KEY" />
</appSettings># Run CMD as Administrator
sc create ExchangeRateService binPath="C:\Services\ExchangeRateService\ExchangeTransferWinService.exe" start=auto
sc start ExchangeRateService-- Check staging table
SELECT * FROM ExchangeRate_Staging ORDER BY CreatedAt DESC
-- Check main table
SELECT * FROM ExchangeRate ORDER BY RateDate DESC, CurrencyCode
-- Verify sync
SELECT
CurrencyCode,
Rate,
RateDate,
UpdatedAt
FROM ExchangeRate
WHERE RateDate = CAST(GETDATE() AS DATE)-- Change fetch interval (2 hours)
UPDATE ServiceSettings SET IntervalMinutes = 120
-- Pause service
UPDATE ServiceSettings SET IsActive = 0
-- Resume service
UPDATE ServiceSettings SET IsActive = 1
-- Update API URL
UPDATE ServiceSettings SET ApiUrl = 'https://new-api.com/rates'eventvwr.msc β Application logs- Check
ApiUrlandApiKeyin config - Verify network connectivity
- Check API rate limits
-- Check staging table
SELECT COUNT(*) FROM ExchangeRate_Staging
-- Check for errors in logs
-- Review transaction rollbacks-- Check existing records
SELECT CurrencyCode, RateDate, COUNT(*)
FROM ExchangeRate
GROUP BY CurrencyCode, RateDate
HAVING COUNT(*) > 1- β API keys in configuration (not hardcoded)
- β SQL parameterized queries (no injection risk)
- β Least privilege database access
- β Transaction rollback on errors
- β Encrypted connection strings (optional)
- GitHub: @Melekdmr
- Issues: Report a bug