Skip to content

Commit c4b533c

Browse files
committed
impl catalog repos + dependency injection
1 parent 03923ab commit c4b533c

File tree

7 files changed

+328
-7
lines changed

7 files changed

+328
-7
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using Microservice.Catalog.Infrastructure.Interfaces;
2+
using Microservice.Catalog.Infrastructure.Repositories;
3+
using Microsoft.Extensions.DependencyInjection;
4+
5+
namespace Microservice.Catalog.Infrastructure.DependencyInjection;
6+
7+
public static class CatalogBrandDependencyInjection
8+
{
9+
public static IServiceCollection AddCatalogBrandRepository(this IServiceCollection @this, string connectionString)
10+
{
11+
@this.AddKeyedScoped<string>(CatalogBrandRepository.CONNECTION_STRING_KEY, (_, _) => connectionString);
12+
@this.AddScoped<ICatalogBrandRepository, ICatalogBrandRepository>();
13+
14+
return @this;
15+
}
16+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,21 @@ public static IServiceCollection AddCatalogItemRepository(this IServiceCollectio
1010
{
1111
@this.AddKeyedScoped<string>(CatalogItemRepository.CONNECTION_STRING_KEY, (serviceProvider, key) => connectionString);
1212
@this.AddScoped<ICatalogItemRepository, CatalogItemRepository>();
13+
@this.AddScoped<CatalogItemRepository>();
14+
15+
return @this;
16+
}
17+
18+
public static IServiceScope SetupCatalogDatabase(this IServiceScope @this)
19+
{
20+
IServiceProvider provider = @this.ServiceProvider;
21+
CatalogItemRepository? repository = provider.GetService<CatalogItemRepository>();
22+
23+
if (repository is null)
24+
return @this;
25+
26+
Task ensureDbTask = repository.EnsureDbExistsAsync();
27+
ensureDbTask.Wait();
1328

1429
return @this;
1530
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using Microservice.Catalog.Infrastructure.Interfaces;
2+
using Microservice.Catalog.Infrastructure.Repositories;
3+
using Microsoft.Extensions.DependencyInjection;
4+
5+
namespace Microservice.Catalog.Infrastructure.DependencyInjection;
6+
7+
public static class CatalogTypeDependencyInjection
8+
{
9+
public static IServiceCollection AddCatalogTypeRepository(this IServiceCollection @this, string connectionString)
10+
{
11+
@this.AddKeyedSingleton<string>(CatalogTypeRepository.CONNECTION_STRING_KEY, connectionString);
12+
@this.AddScoped<ICatalogTypeRepository, CatalogTypeRepository>();
13+
14+
return @this;
15+
}
16+
}

src/Microservices/CatalogMicroservice/CatalogMicroservice.Infrastructure/Interfaces/ICatalogBrandRepository.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ namespace Microservice.Catalog.Infrastructure.Interfaces;
44

55
public interface ICatalogBrandRepository
66
{
7-
Task<CatalogBrand> GetBrandByIdAsync(int brandId, CancellationToken cancellationToken = default);
7+
Task<CatalogBrand?> GetBrandByIdAsync(int brandId, CancellationToken cancellationToken = default);
88
Task<IEnumerable<CatalogBrand>> GetBrandsAsync(CancellationToken cancellationToken = default);
99
}

src/Microservices/CatalogMicroservice/CatalogMicroservice.Infrastructure/Interfaces/ICatalogTypeRepository.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ namespace Microservice.Catalog.Infrastructure.Interfaces;
44

55
public interface ICatalogTypeRepository
66
{
7-
Task<CatalogType> GetCatalogTypeAsync(int typeId, CancellationToken cancellationToken = default);
7+
Task<CatalogType?> GetCatalogTypeAsync(int typeId, CancellationToken cancellationToken = default);
88
Task<IEnumerable<CatalogType>> GetCatalogTypesAsync(CancellationToken cancellationToken = default);
99
}

src/Microservices/CatalogMicroservice/CatalogMicroservice.Infrastructure/Repositories/CatalogBrandRepository.cs

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -144,10 +144,10 @@ INSERT INTO [Catalog]([Name], [Description], [Price], [PictureUri], [CatalogType
144144
}
145145
}
146146

147-
public async Task<CatalogBrand> GetBrandByIdAsync(int brandId, CancellationToken cancellationToken = default)
147+
public async Task<CatalogBrand?> GetBrandByIdAsync(int brandId, CancellationToken cancellationToken = default)
148148
{
149149
string sqlString = $@"
150-
SELECT B.Id B.Brand FROM [CatalogBrand] B
150+
SELECT B.Id B.Brand FROM [CatalogBrands] B
151151
WHERE B.Id = @{nameof(brandId)}
152152
";
153153

@@ -160,7 +160,20 @@ SELECT B.Id B.Brand FROM [CatalogBrand] B
160160

161161
command.AddParameterValue($"@{nameof(brandId)}", SqlDbType.Int, brandId);
162162

163-
return null;
163+
SqlDataReader reader = await command.ExecuteReaderAsync(cancellationToken);
164+
CatalogBrand? result = null;
165+
166+
if (await reader.ReadAsync(cancellationToken))
167+
{
168+
int i = 0;
169+
result = new CatalogBrand
170+
{
171+
Id = reader.GetInt32(i++),
172+
Brand = reader.GetString(i++)
173+
};
174+
}
175+
176+
return result;
164177
}
165178
catch (Exception e)
166179
{
@@ -174,9 +187,44 @@ SELECT B.Id B.Brand FROM [CatalogBrand] B
174187
}
175188
}
176189

177-
public Task<IEnumerable<CatalogBrand>> GetBrandsAsync(CancellationToken cancellationToken = default)
190+
public async Task<IEnumerable<CatalogBrand>> GetBrandsAsync(CancellationToken cancellationToken = default)
178191
{
179-
throw new System.NotImplementedException();
192+
string sqlString = $@"
193+
SELECT B.Id, B.Brand FROM [CatalogBrands] B
194+
";
195+
196+
try
197+
{
198+
await using SqlConnection connection = new SqlConnection(_connectionString);
199+
using SqlCommand command = connection.CreateCommand();
200+
201+
command.CommandText = sqlString;
202+
List<CatalogBrand> result = [];
203+
204+
SqlDataReader reader = await command.ExecuteReaderAsync(cancellationToken);
205+
while (await reader.ReadAsync(cancellationToken))
206+
{
207+
int i = 0;
208+
CatalogBrand brand = new CatalogBrand
209+
{
210+
Id = reader.GetInt32(i++),
211+
Brand = reader.GetString(i++)
212+
};
213+
214+
result.Add(brand);
215+
}
216+
217+
return result;
218+
}
219+
catch (Exception e)
220+
{
221+
_logger.LogError(
222+
e,
223+
"Could not fetch catalog brands due to internal error"
224+
);
225+
226+
throw e;
227+
}
180228
}
181229
}
182230

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
using System.Data;
2+
using Microservice.Catalog.Common.Models;
3+
using Microservice.Catalog.Infrastructure.Helpers;
4+
using Microservice.Catalog.Infrastructure.Interfaces;
5+
using Microsoft.Data.SqlClient;
6+
using Microsoft.Extensions.DependencyInjection;
7+
using Microsoft.Extensions.Logging;
8+
9+
namespace Microservice.Catalog.Infrastructure.Repositories;
10+
11+
internal class CatalogTypeRepository: ICatalogTypeRepository
12+
{
13+
internal const string CONNECTION_STRING_KEY = "catalog-type";
14+
15+
private readonly string _connectionString;
16+
private readonly ILogger _logger;
17+
18+
public CatalogTypeRepository(IKeyedServiceProvider keyedServiceProvider, ILogger<CatalogBrandRepository> logger)
19+
{
20+
string? connectionString = keyedServiceProvider.GetKeyedService<string>(CONNECTION_STRING_KEY);
21+
if (connectionString is null)
22+
throw new InvalidOperationException("Could not create CatalogTypeRepository due to missing connection string");
23+
24+
_connectionString = connectionString;
25+
_logger = logger;
26+
}
27+
28+
public async Task EnsureDbExistsAsync(CancellationToken cancellationToken = default)
29+
{
30+
string sqlString = @"
31+
DECLARE @insertBrands INT = 0;
32+
DECLARE @insertTypes INT = 0;
33+
DECLARE @insertCatalog INT = 0;
34+
35+
IF (DB_ID('CatalogDatabase') IS NOT NULL)
36+
BEGIN
37+
PRINT 'Database ""CatalogDatabase"" exists';
38+
END
39+
ELSE BEGIN
40+
CREATE DATABASE [CatalogDatabase];
41+
END;
42+
43+
USE [CatalogDatabase];
44+
45+
IF (OBJECT_ID('CatalogBrands') IS NOT NULL)
46+
BEGIN
47+
PRINT 'Table ""CatalogBrands"" exists';
48+
END
49+
ELSE BEGIN
50+
CREATE TABLE [CatalogBrands] (
51+
Id INT NOT NULL PRIMARY KEY IDENTITY(1, 1),
52+
Brand NVARCHAR(100) NOT NULL,
53+
);
54+
SET @insertBrands = 1;
55+
END;
56+
57+
IF (OBJECT_ID('CatalogTypes') IS NOT NULL)
58+
BEGIN
59+
PRINT 'Table ""CatalogTypes"" exists';
60+
END
61+
ELSE BEGIN
62+
CREATE TABLE CatalogTypes (
63+
Id INT NOT NULL PRIMARY KEY IDENTITY(1, 1),
64+
[Type] NVARCHAR(100) NOT NULL
65+
);
66+
SET @insertTypes = 1;
67+
END;
68+
69+
IF (OBJECT_ID('Catalog') IS NOT NULL)
70+
BEGIN
71+
PRINT 'Table ""Catalog"" exists';
72+
END
73+
ELSE BEGIN
74+
CREATE TABLE [Catalog] (
75+
Id INT PRIMARY KEY NOT NULL IDENTITY(1, 1),
76+
[Name] VARCHAR(50) NOT NULL,
77+
[Description] VARCHAR(MAX),
78+
Price DECIMAL(18, 2) NOT NULL,
79+
PictureUri VARCHAR(MAX) NOT NULL,
80+
CatalogTypeId INT NOT NULL,
81+
CatalogBrandId INT NOT NULL
82+
);
83+
SET @insertCatalog = 1;
84+
END;
85+
86+
IF @insertBrands = 1
87+
BEGIN
88+
PRINT 'Inserting Brands';
89+
INSERT INTO [CatalogBrands]([Brand])
90+
VALUES ('Azure'),
91+
('.NET'),
92+
('Visual Studio'),
93+
('SQL Server'),
94+
('Other');
95+
END;
96+
97+
IF @insertTypes = 1
98+
BEGIN
99+
PRINT 'Inserting types';
100+
INSERT INTO [CatalogTypes]([Type])
101+
VALUES ('Mug'),
102+
('T-Shirt'),
103+
('Sheet'),
104+
('USB Memory Stick');
105+
END;
106+
107+
IF @insertCatalog = 1
108+
BEGIN
109+
PRINT 'Inserting Types';
110+
INSERT INTO [Catalog]([Name], [Description], [Price], [PictureUri], [CatalogTypeId], [CatalogBrandId])
111+
VALUEs ('.NET Bot Black Sweatshirt','.NET Bot Black Sweatshirt',19.50,'http://catalogbaseurltobereplaced/images/products/1.png',2,2),
112+
('.NET Black & White Mug','.NET Black & White Mug',8.50,'http://catalogbaseurltobereplaced/images/products/2.png',1,2),
113+
('Prism White T-Shirt','Prism White T-Shirt',12.00,'http://catalogbaseurltobereplaced/images/products/3.png',2,5),
114+
('.NET Foundation Sweatshirt','.NET Foundation Sweatshirt',12.00,'http://catalogbaseurltobereplaced/images/products/4.png',2,2),
115+
('Roslyn Red Sheet','Roslyn Red Sheet',8.50,'http://catalogbaseurltobereplaced/images/products/5.png',3,5),
116+
('.NET Blue Sweatshirt','.NET Blue Sweatshirt',12.00,'http://catalogbaseurltobereplaced/images/products/6.png',2,2),
117+
('Roslyn Red T-Shirt','Roslyn Red T-Shirt',12.00,'http://catalogbaseurltobereplaced/images/products/7.png',2,5),
118+
('Kudu Purple Sweatshirt','Kudu Purple Sweatshirt',8.50,'http://catalogbaseurltobereplaced/images/products/8.png',2,5),
119+
('Cup<T> White Mug','Cup<T> White Mug',12.00,'http://catalogbaseurltobereplaced/images/products/9.png',1,5),
120+
('.NET Foundation Sheet','.NET Foundation Sheet',12.00,'http://catalogbaseurltobereplaced/images/products/10.png',3,2),
121+
('Cup<T> Sheet','Cup<T> Sheet',8.50,'http://catalogbaseurltobereplaced/images/products/11.png',3,2),
122+
('Prism White TShirt','Prism White TShirt',12.00,'http://catalogbaseurltobereplaced/images/products/12.png',2,5);
123+
END;
124+
""";
125+
126+
try
127+
{
128+
await using SqlConnection connection = new SqlConnection(_connectionString);
129+
using SqlCommand command = connection.CreateCommand();
130+
131+
command.CommandText = sqlString;
132+
await command.ExecuteNonQueryAsync(cancellationToken);
133+
134+
return;
135+
}
136+
catch (Exception e)
137+
{
138+
_logger.LogError(
139+
e,
140+
"Could complete database setup due to internal error"
141+
);
142+
143+
throw e;
144+
}
145+
}
146+
public async Task<CatalogType?> GetCatalogTypeAsync(int typeId, CancellationToken cancellationToken = default)
147+
{
148+
string sqlString = $@"
149+
SELECT T.Id, T.[Type] from [CatalogTypes] T
150+
WHERE T.Id = @{nameof(typeId)}
151+
";
152+
try
153+
{
154+
await using SqlConnection connection = new SqlConnection(_connectionString);
155+
using SqlCommand command = connection.CreateCommand();
156+
157+
command.CommandText = sqlString;
158+
159+
command.AddParameterValue($"@{nameof(typeId)}", SqlDbType.Int, typeId);
160+
161+
SqlDataReader reader = await command.ExecuteReaderAsync(cancellationToken);
162+
CatalogType? type = null;
163+
164+
if (await reader.ReadAsync(cancellationToken))
165+
{
166+
int i = 0;
167+
type = new CatalogType
168+
{
169+
Id = reader.GetInt32(i++),
170+
Type = reader.GetString(i++)
171+
};
172+
}
173+
174+
return type;
175+
}
176+
catch (Exception e)
177+
{
178+
_logger.LogError(
179+
e,
180+
"Could not fetch catalog type with id = {TypeId} due to internal error",
181+
typeId
182+
);
183+
184+
throw e;
185+
}
186+
}
187+
188+
public async Task<IEnumerable<CatalogType>> GetCatalogTypesAsync(CancellationToken cancellationToken = default)
189+
{
190+
string sqlString = $@"
191+
SELECT T.Id, T.[Type] from [CatalogTypes]
192+
";
193+
194+
try
195+
{
196+
await using SqlConnection connection = new SqlConnection(_connectionString);
197+
using SqlCommand command = connection.CreateCommand();
198+
199+
command.CommandText = sqlString;
200+
SqlDataReader reader = await command.ExecuteReaderAsync(cancellationToken);
201+
202+
List<CatalogType> result = [];
203+
while (await reader.ReadAsync(cancellationToken))
204+
{
205+
int i = 0;
206+
CatalogType type = new CatalogType
207+
{
208+
Id = reader.GetInt32(i++),
209+
Type = reader.GetString(i++)
210+
};
211+
result.Add(type);
212+
}
213+
214+
return result;
215+
}
216+
catch (Exception e)
217+
{
218+
_logger.LogError(
219+
e,
220+
"Could not fetch catalog types due to internal error"
221+
);
222+
223+
throw e;
224+
}
225+
}
226+
}

0 commit comments

Comments
 (0)