diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..93af010 --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ + +bin/ +obj/ + + +*.user +*.suo +*.userosscache +*.sln.docstates + + +*.vs/ +*.vscode/ + +*.bak +*.tmp + +*.log \ No newline at end of file diff --git a/ThirdCourseTask.Data/Entities/TaskEntity.cs b/ThirdCourseTask.Data/Entities/TaskEntity.cs new file mode 100644 index 0000000..a810271 --- /dev/null +++ b/ThirdCourseTask.Data/Entities/TaskEntity.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ThirdCourseTask.Data.Entities +{ + public class TaskEntity + { + public int Id { get; set; } + public string Title { get; set; } + public string Description { get; set; } + public bool IsCompleted { get; set; } + public DateTime CreatedAt { get; set; } + } +} diff --git a/ThirdCourseTask.Data/ThirdCourseTask.Data.csproj b/ThirdCourseTask.Data/ThirdCourseTask.Data.csproj new file mode 100644 index 0000000..6bc3899 --- /dev/null +++ b/ThirdCourseTask.Data/ThirdCourseTask.Data.csproj @@ -0,0 +1,13 @@ + + + + net8.0 + enable + enable + + + + + + + diff --git a/ThirdCourseTask.Infrastructure/Database/DbConnectionFactory.cs b/ThirdCourseTask.Infrastructure/Database/DbConnectionFactory.cs new file mode 100644 index 0000000..916d181 --- /dev/null +++ b/ThirdCourseTask.Infrastructure/Database/DbConnectionFactory.cs @@ -0,0 +1,48 @@ +using System.Data; +using Microsoft.Data.SqlClient; +using Npgsql; +using Microsoft.Extensions.Configuration; + +namespace ThirdCourseTask.Infrastructure.Database; + +public sealed class DbConnectionFactory : IDbConnectionFactory +{ + private readonly string _sqlConnectionString; + private readonly string _pgConnectionString; + private readonly DbProvider _provider; + + public DbConnectionFactory(IConfiguration configuration) + { + _sqlConnectionString = configuration.GetConnectionString("SqlServer") + ?? throw new InvalidOperationException("Missing 'SqlServer' connection string."); + + _pgConnectionString = configuration.GetConnectionString("Postgres") + ?? throw new InvalidOperationException("Missing 'Postgres' connection string."); + + string? providerFromEnv = Environment.GetEnvironmentVariable("DB_PROVIDER"); + + if (providerFromEnv != null && providerFromEnv.ToLowerInvariant() == "postgres") + { + _provider = DbProvider.Postgres; + } + else + { + _provider = DbProvider.SqlServer; + } + } + + public IDbConnection Create() + { + if (_provider == DbProvider.Postgres) + { + return new NpgsqlConnection(_pgConnectionString); + } + + if (_provider == DbProvider.SqlServer) + { + return new SqlConnection(_sqlConnectionString); + } + + throw new InvalidOperationException("Unsupported provider: " + _provider); + } +} diff --git a/ThirdCourseTask.Infrastructure/Database/DbProvider.cs b/ThirdCourseTask.Infrastructure/Database/DbProvider.cs new file mode 100644 index 0000000..94ee7d1 --- /dev/null +++ b/ThirdCourseTask.Infrastructure/Database/DbProvider.cs @@ -0,0 +1,6 @@ +namespace ThirdCourseTask.Infrastructure.Database; +public enum DbProvider +{ + SqlServer, + Postgres +} diff --git a/ThirdCourseTask.Infrastructure/Database/IDbConnectionFactory.cs b/ThirdCourseTask.Infrastructure/Database/IDbConnectionFactory.cs new file mode 100644 index 0000000..78ffe38 --- /dev/null +++ b/ThirdCourseTask.Infrastructure/Database/IDbConnectionFactory.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ThirdCourseTask.Infrastructure.Database +{ + public interface IDbConnectionFactory + { + IDbConnection Create(); + } +} diff --git a/ThirdCourseTask.Infrastructure/Repositories/Abstractions/ITaskRepository.cs b/ThirdCourseTask.Infrastructure/Repositories/Abstractions/ITaskRepository.cs new file mode 100644 index 0000000..3df27b4 --- /dev/null +++ b/ThirdCourseTask.Infrastructure/Repositories/Abstractions/ITaskRepository.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using ThirdCourseTask.Data.Entities; + +namespace ThirdCourseTask.Infrastructure.Database.Repositories.Abstractions +{ + public interface ITaskRepository + { + Task CreateAsync(TaskEntity entity); + Task> GetAllAsync(); + Task SetCompletedAsync(int taskId, bool isCompleted); + Task DeleteAsync(int taskId); + } +} diff --git a/ThirdCourseTask.Infrastructure/Repositories/Implementations/TaskRepository.cs b/ThirdCourseTask.Infrastructure/Repositories/Implementations/TaskRepository.cs new file mode 100644 index 0000000..ff4817e --- /dev/null +++ b/ThirdCourseTask.Infrastructure/Repositories/Implementations/TaskRepository.cs @@ -0,0 +1,85 @@ +using System.Data; +using Dapper; +using ThirdCourseTask.Data.Entities; +using ThirdCourseTask.Infrastructure.Database.Repositories.Abstractions; + +namespace ThirdCourseTask.Infrastructure.Database.Repositories.Implementations +{ + public class TaskRepository : ITaskRepository + { + private readonly IDbConnectionFactory _factory; + + public TaskRepository(IDbConnectionFactory connectionFactory) + { + _factory = connectionFactory; + } + + public async Task CreateAsync(TaskEntity entity) + { + const string sql = @" + INSERT INTO dbo.Tasks(Title, [Description], IsCompleted, CreatedAt) + VALUES (@Title, @Description, @IsCompleted, SYSUTCDATETIME()); + SELECT CAST(SCOPE_IDENTITY() AS INT);"; + + try + { + using var dbConnection = _factory.Create(); + int createdTaskId = await dbConnection.ExecuteScalarAsync(sql, entity); + return createdTaskId; + } + catch (Exception ex) + { + throw new InvalidOperationException("Failed to create a new task.", ex); + } + } + + public async Task> GetAllAsync() + { + const string sql = @"SELECT Id, Title, [Description], IsCompleted, CreatedAt + FROM dbo.Tasks ORDER BY CreatedAt DESC;"; + + try + { + using var dbConnection = _factory.Create(); + var tasks = await dbConnection.QueryAsync(sql); + return tasks.ToList(); + } + catch (Exception ex) + { + throw new InvalidOperationException("Failed to retrieve tasks.", ex); + } + } + + public async Task SetCompletedAsync(int id, bool isCompleted) + { + const string sql = @"UPDATE dbo.Tasks SET IsCompleted = @isCompleted WHERE Id = @id;"; + + try + { + using var dbConnection = _factory.Create(); + int affectedRows = await dbConnection.ExecuteAsync(sql, new { id, isCompleted }); + return affectedRows > 0; + } + catch (Exception ex) + { + throw new InvalidOperationException("Failed to update completion status for task Id=" + id + ".", ex); + } + } + + public async Task DeleteAsync(int id) + { + const string sql = @"DELETE FROM dbo.Tasks WHERE Id = @id;"; + + try + { + using var dbConnection = _factory.Create(); + int affectedRows = await dbConnection.ExecuteAsync(sql, new { id }); + return affectedRows > 0; + } + catch (Exception ex) + { + throw new InvalidOperationException("Failed to delete task Id=" + id + ".", ex); + } + } + } +} diff --git a/ThirdCourseTask.Infrastructure/Services/Abstractions/ITaskService.cs b/ThirdCourseTask.Infrastructure/Services/Abstractions/ITaskService.cs new file mode 100644 index 0000000..e266b84 --- /dev/null +++ b/ThirdCourseTask.Infrastructure/Services/Abstractions/ITaskService.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using ThirdCourseTask.Data.Entities; + +namespace ThirdCourseTask.Infrastructure.Services.Abstractions +{ + public interface ITaskService + { + Task AddAsync(string title, string? description); + Task> GetAllAsync(); + Task CompleteAsync(int id, bool isCompleted); + Task RemoveAsync(int id); + } +} diff --git a/ThirdCourseTask.Infrastructure/Services/Implementations/TaskService.cs b/ThirdCourseTask.Infrastructure/Services/Implementations/TaskService.cs new file mode 100644 index 0000000..311ee7d --- /dev/null +++ b/ThirdCourseTask.Infrastructure/Services/Implementations/TaskService.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using ThirdCourseTask.Data.Entities; +using ThirdCourseTask.Infrastructure.Database.Repositories.Abstractions; +using ThirdCourseTask.Infrastructure.Services.Abstractions; + +namespace ThirdCourseTask.Infrastructure.Services.Implementations +{ + public class TaskService : ITaskService + { + private readonly ITaskRepository _taskRepository; + + public TaskService(ITaskRepository taskRepository) + { + _taskRepository = taskRepository; + } + + public async Task AddAsync(string title, string? description) + { + return await _taskRepository.CreateAsync(new TaskEntity + { + Title = title, + Description = description, + IsCompleted = false, + }); + } + + public async Task> GetAllAsync() + { + return await _taskRepository.GetAllAsync(); + } + + + public async Task CompleteAsync(int id, bool isCompleted) + { + return await _taskRepository.SetCompletedAsync(id, isCompleted); + } + + + public async Task RemoveAsync(int id) + { + return await _taskRepository.DeleteAsync(id); + } + + } +} diff --git a/ThirdCourseTask.Infrastructure/SqlScripts/DataBaseInit.sql b/ThirdCourseTask.Infrastructure/SqlScripts/DataBaseInit.sql new file mode 100644 index 0000000..bedcf26 --- /dev/null +++ b/ThirdCourseTask.Infrastructure/SqlScripts/DataBaseInit.sql @@ -0,0 +1,10 @@ +IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'Tasks') +BEGIN + CREATE TABLE dbo.Tasks ( + Id INT IDENTITY(1,1) PRIMARY KEY, + Title NVARCHAR(200) NOT NULL, + Description NVARCHAR(MAX) NULL, + IsCompleted BIT NOT NULL DEFAULT(0), + CreatedAt DATETIME2(0) NOT NULL DEFAULT (SYSUTCDATETIME()) + ); +END diff --git a/ThirdCourseTask.Infrastructure/ThirdCourseTask.Infrastructure.csproj b/ThirdCourseTask.Infrastructure/ThirdCourseTask.Infrastructure.csproj new file mode 100644 index 0000000..4153347 --- /dev/null +++ b/ThirdCourseTask.Infrastructure/ThirdCourseTask.Infrastructure.csproj @@ -0,0 +1,24 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + + + + + + + diff --git a/ThirdCourseTask.sln b/ThirdCourseTask.sln new file mode 100644 index 0000000..6fc3ecd --- /dev/null +++ b/ThirdCourseTask.sln @@ -0,0 +1,67 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Элементы решения", "Элементы решения", "{754FC069-D67B-A9D7-50A1-8D1CA196D8F1}" + ProjectSection(SolutionItems) = preProject + .gitignore = .gitignore + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThirdCourseTask.Infrastructure", "ThirdCourseTask.Infrastructure\ThirdCourseTask.Infrastructure.csproj", "{396FDC09-A11B-4031-9425-5A785CDD357E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThirdCourseTask", "ThirdCourseTask\ThirdCourseTask.csproj", "{4667C4D6-91DD-4431-8A08-6500E1F79C82}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThirdCourseTask.Data", "ThirdCourseTask.Data\ThirdCourseTask.Data.csproj", "{A508F38B-0BC5-4E68-9067-932100DA97B5}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {396FDC09-A11B-4031-9425-5A785CDD357E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {396FDC09-A11B-4031-9425-5A785CDD357E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {396FDC09-A11B-4031-9425-5A785CDD357E}.Debug|x64.ActiveCfg = Debug|Any CPU + {396FDC09-A11B-4031-9425-5A785CDD357E}.Debug|x64.Build.0 = Debug|Any CPU + {396FDC09-A11B-4031-9425-5A785CDD357E}.Debug|x86.ActiveCfg = Debug|Any CPU + {396FDC09-A11B-4031-9425-5A785CDD357E}.Debug|x86.Build.0 = Debug|Any CPU + {396FDC09-A11B-4031-9425-5A785CDD357E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {396FDC09-A11B-4031-9425-5A785CDD357E}.Release|Any CPU.Build.0 = Release|Any CPU + {396FDC09-A11B-4031-9425-5A785CDD357E}.Release|x64.ActiveCfg = Release|Any CPU + {396FDC09-A11B-4031-9425-5A785CDD357E}.Release|x64.Build.0 = Release|Any CPU + {396FDC09-A11B-4031-9425-5A785CDD357E}.Release|x86.ActiveCfg = Release|Any CPU + {396FDC09-A11B-4031-9425-5A785CDD357E}.Release|x86.Build.0 = Release|Any CPU + {4667C4D6-91DD-4431-8A08-6500E1F79C82}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4667C4D6-91DD-4431-8A08-6500E1F79C82}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4667C4D6-91DD-4431-8A08-6500E1F79C82}.Debug|x64.ActiveCfg = Debug|Any CPU + {4667C4D6-91DD-4431-8A08-6500E1F79C82}.Debug|x64.Build.0 = Debug|Any CPU + {4667C4D6-91DD-4431-8A08-6500E1F79C82}.Debug|x86.ActiveCfg = Debug|Any CPU + {4667C4D6-91DD-4431-8A08-6500E1F79C82}.Debug|x86.Build.0 = Debug|Any CPU + {4667C4D6-91DD-4431-8A08-6500E1F79C82}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4667C4D6-91DD-4431-8A08-6500E1F79C82}.Release|Any CPU.Build.0 = Release|Any CPU + {4667C4D6-91DD-4431-8A08-6500E1F79C82}.Release|x64.ActiveCfg = Release|Any CPU + {4667C4D6-91DD-4431-8A08-6500E1F79C82}.Release|x64.Build.0 = Release|Any CPU + {4667C4D6-91DD-4431-8A08-6500E1F79C82}.Release|x86.ActiveCfg = Release|Any CPU + {4667C4D6-91DD-4431-8A08-6500E1F79C82}.Release|x86.Build.0 = Release|Any CPU + {A508F38B-0BC5-4E68-9067-932100DA97B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A508F38B-0BC5-4E68-9067-932100DA97B5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A508F38B-0BC5-4E68-9067-932100DA97B5}.Debug|x64.ActiveCfg = Debug|Any CPU + {A508F38B-0BC5-4E68-9067-932100DA97B5}.Debug|x64.Build.0 = Debug|Any CPU + {A508F38B-0BC5-4E68-9067-932100DA97B5}.Debug|x86.ActiveCfg = Debug|Any CPU + {A508F38B-0BC5-4E68-9067-932100DA97B5}.Debug|x86.Build.0 = Debug|Any CPU + {A508F38B-0BC5-4E68-9067-932100DA97B5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A508F38B-0BC5-4E68-9067-932100DA97B5}.Release|Any CPU.Build.0 = Release|Any CPU + {A508F38B-0BC5-4E68-9067-932100DA97B5}.Release|x64.ActiveCfg = Release|Any CPU + {A508F38B-0BC5-4E68-9067-932100DA97B5}.Release|x64.Build.0 = Release|Any CPU + {A508F38B-0BC5-4E68-9067-932100DA97B5}.Release|x86.ActiveCfg = Release|Any CPU + {A508F38B-0BC5-4E68-9067-932100DA97B5}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/ThirdCourseTask/Program.cs b/ThirdCourseTask/Program.cs new file mode 100644 index 0000000..303a58e --- /dev/null +++ b/ThirdCourseTask/Program.cs @@ -0,0 +1,70 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using ThirdCourseTask.Infrastructure.Database; +using ThirdCourseTask.Infrastructure.Database.Repositories.Abstractions; +using ThirdCourseTask.Infrastructure.Database.Repositories.Implementations; +using ThirdCourseTask.Infrastructure.Services.Abstractions; +using ThirdCourseTask.Infrastructure.Services.Implementations; +using ThirdCourseTask.UI; + +Console.WriteLine("Select a database:"); +Console.WriteLine("1) SQL Server"); +Console.WriteLine("2) PostgreSQL"); + +string? choice = null; + +while (choice != "1" && choice != "2") +{ + Console.Write("Enter 1 or 2: "); + choice = Console.ReadLine(); +} + +if (choice == "2") +{ + Environment.SetEnvironmentVariable("DB_PROVIDER", "Postgres"); +} +else +{ + Environment.SetEnvironmentVariable("DB_PROVIDER", "SqlServer"); +} + +using var host = Host.CreateDefaultBuilder(args) + .ConfigureAppConfiguration(cfg => + { + cfg.Sources.Clear(); + cfg.SetBasePath(AppContext.BaseDirectory); + cfg.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true); + cfg.AddEnvironmentVariables(); + }) + .ConfigureServices(services => + { + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + }) + .Build(); + + +var inputService = host.Services.GetRequiredService(); + +while (true) +{ + try + { + await inputService.RunAsync(); + } + catch (ApplicationException ex) + { + Console.WriteLine("Application error: " + ex.Message); + } + catch (InvalidOperationException ex) + { + Console.WriteLine("Operation error: " + ex.Message); + } + catch (Exception ex) + { + Console.WriteLine("Unexpected error: " + ex.Message); + } +} diff --git a/ThirdCourseTask/ThirdCourseTask.csproj b/ThirdCourseTask/ThirdCourseTask.csproj new file mode 100644 index 0000000..5d71abb --- /dev/null +++ b/ThirdCourseTask/ThirdCourseTask.csproj @@ -0,0 +1,25 @@ + + + + + + + + + + + + Exe + net9.0 + enable + enable + + + + + + PreserveNewest + + + + diff --git a/ThirdCourseTask/UI/ConsoleInputService.cs b/ThirdCourseTask/UI/ConsoleInputService.cs new file mode 100644 index 0000000..f85123b --- /dev/null +++ b/ThirdCourseTask/UI/ConsoleInputService.cs @@ -0,0 +1,199 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using ThirdCourseTask.Infrastructure.Services.Abstractions; + +namespace ThirdCourseTask.UI +{ + public class ConsoleInputService : IInputService + { + private ITaskService _taskService; + + public ConsoleInputService(ITaskService taskService) + { + _taskService = taskService; + } + + public async Task RunAsync() + { + var key = Console.ReadLine(); + Menu(); + switch (key) + { + case "1": + { + await AddTaskAsync(); + break; + } + + + case "2": + { + await ListTasksAsync(); + break; + } + + + case "3": + { + await ChangeTaskStatus(); + break; + } + + case "4": + { + await RemoveTaskByIdAsync(); + break; + } + + case "0": + return; + + default: + Console.WriteLine("The operation you selected does not exist. Please try again."); + break; + } + } + + private void Menu() + { + Console.WriteLine("\n=== Task Manager ==="); + Console.WriteLine("1) Add Task"); + Console.WriteLine("2) Show All Tasks"); + Console.WriteLine("3) Change Task status"); + Console.WriteLine("4) Remove Task By Id"); + } + + public async Task AddTaskAsync() + { + try + { + Console.Write("Title: "); + string? title = Console.ReadLine(); + + if (string.IsNullOrWhiteSpace(title)) + { + Console.WriteLine("Title cannot be empty."); + return; + } + + Console.Write("Description: "); + string? description = Console.ReadLine(); + + int createdTaskId = await _taskService.AddAsync(title, description); + Console.WriteLine("Created. Id=" + createdTaskId); + } + + catch (Exception ex) + { + Console.WriteLine("Unexpected error: " + ex.Message); + } + } + + private async Task ListTasksAsync() + { + try + { + var tasks = await _taskService.GetAllAsync(); + + if (tasks.Count == 0) + { + Console.WriteLine("Empty."); + return; + } + + foreach (var task in tasks) + { + Console.WriteLine("Id: " + task.Id + ", Title: " + task.Title + ", Completed: " + task.IsCompleted + ", CreatedAt: " + task.CreatedAt); + } + } + + catch (Exception ex) + { + Console.WriteLine("Unexpected error: " + ex.Message); + } + } + + private async Task ChangeTaskStatus() + { + try + { + Console.Write("Id: "); + string? input = Console.ReadLine(); + + int taskId; + bool parsed = int.TryParse(input, out taskId); + + if (!parsed) + { + Console.WriteLine("Invalid Id."); + return; + } + + Console.Write("Completed? (y/n): "); + string? ans = Console.ReadLine(); + + bool isCompleted = false; + + if (ans == "y" || ans == "1") + { + isCompleted = true; + } + + bool updated = await _taskService.CompleteAsync(taskId, isCompleted); + + if (updated) + { + Console.WriteLine("Updated."); + } + else + { + Console.WriteLine("Not found."); + } + } + + catch (Exception ex) + { + Console.WriteLine("Unexpected error: " + ex.Message); + } + + } + + private async Task RemoveTaskByIdAsync() + { + try + { + Console.Write("Id: "); + string? input = Console.ReadLine(); + + int taskId; + bool parsed = int.TryParse(input, out taskId); + + if (!parsed) + { + Console.WriteLine("Invalid Id."); + return; + } + + bool deleted = await _taskService.RemoveAsync(taskId); + + if (deleted) + { + Console.WriteLine("Deleted."); + } + else + { + Console.WriteLine("Not found."); + } + } + + catch (Exception ex) + { + Console.WriteLine("Unexpected error: " + ex.Message); + } + + } + } +} diff --git a/ThirdCourseTask/UI/IConsoleInputService.cs b/ThirdCourseTask/UI/IConsoleInputService.cs new file mode 100644 index 0000000..0cb3cd2 --- /dev/null +++ b/ThirdCourseTask/UI/IConsoleInputService.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ThirdCourseTask.UI +{ + public interface IInputService + { + Task RunAsync(); + } +} diff --git a/ThirdCourseTask/appsettings.json b/ThirdCourseTask/appsettings.json new file mode 100644 index 0000000..0c7b3a0 --- /dev/null +++ b/ThirdCourseTask/appsettings.json @@ -0,0 +1,6 @@ +{ + "ConnectionStrings": { + "SqlServer": "Server=DESKTOP-RMIFAFV\\SQLSERVER2019;Database=ThirdCourseTaskDb;Integrated Security=True", + "Postgres": "Host=localhost;Port=5432;Username=postgres;Password=postgres;Database=thirdcoursetaskdb" + } +}