diff --git a/GottfriedsNackenWebseite/DataAccess/Data/IUserData.cs b/GottfriedsNackenWebseite/DataAccess/Data/IUserData.cs new file mode 100644 index 0000000..4dea7b5 --- /dev/null +++ b/GottfriedsNackenWebseite/DataAccess/Data/IUserData.cs @@ -0,0 +1,12 @@ +using DataAccess.Models; + +namespace DataAccess.Data; + +public interface IUserData +{ + Task> GetUsers(); + Task GetUser(int id); + Task InsertUser(UserModel user); + Task UpdateUser(UserModel user); + Task DeleteUser(int id); +} \ No newline at end of file diff --git a/GottfriedsNackenWebseite/DataAccess/Data/UserData.cs b/GottfriedsNackenWebseite/DataAccess/Data/UserData.cs new file mode 100644 index 0000000..ea0f641 --- /dev/null +++ b/GottfriedsNackenWebseite/DataAccess/Data/UserData.cs @@ -0,0 +1,43 @@ +using DataAccess.DbAccess; +using DataAccess.Models; + +namespace DataAccess.Data; + +public class UserData : IUserData +{ + private readonly ISqlDataAccess _db; + + public UserData(ISqlDataAccess db) + { + _db = db; + } + + public Task> GetUsers() + { + return _db.LoadData("dbo.spUser_GetAll", new { }); + } + + public async Task GetUser(int id) + { + IEnumerable results = await _db.LoadData( + "dbo.spUser_Get", + new { Id = id }); + + return results.FirstOrDefault(); + } + + public Task InsertUser(UserModel user) + { + return _db.SaveData("dbo.spUser_Insert", new { user.FirstName, user.LastName }); + } + + public Task UpdateUser(UserModel user) + { + return _db.SaveData("dbo.spUser_Update", user); + } + + public Task DeleteUser(int id) + { + return _db.SaveData("dbo.spUser_Delete", new { Id = id }); + } +} diff --git a/GottfriedsNackenWebseite/DataAccess/DataAccess.csproj b/GottfriedsNackenWebseite/DataAccess/DataAccess.csproj new file mode 100644 index 0000000..c970e5e --- /dev/null +++ b/GottfriedsNackenWebseite/DataAccess/DataAccess.csproj @@ -0,0 +1,15 @@ + + + + net6.0 + enable + enable + + + + + + + + + diff --git a/GottfriedsNackenWebseite/DataAccess/DbAccess/ISqlDataAccess.cs b/GottfriedsNackenWebseite/DataAccess/DbAccess/ISqlDataAccess.cs new file mode 100644 index 0000000..1ebc1a5 --- /dev/null +++ b/GottfriedsNackenWebseite/DataAccess/DbAccess/ISqlDataAccess.cs @@ -0,0 +1,33 @@ +namespace DataAccess.DbAccess; + +/// +/// Stellt Methoden zur Ausführung von CRUD-Operationen bereit. +/// +public interface ISqlDataAccess +{ + /// + /// Liest Daten aus der Datenbank (Read Operationen). + /// + /// Typ der Objekte die zurückgegeben werden. + /// Typ des Objekts das die Parameter für die SQL-Query enthält. + /// Name der StoredProcedure die ausgeführt werden soll. + /// Das Objekt das die Parameter enthält. + /// Der Name des ConnectionStrings der für die Verbindung verwendet werden soll. + /// Die Ergebnisse der Anfrage. + Task> LoadData( + string storedProcedureName, + TParam parameters, + string connectionId = "Default"); + + /// + /// Führt eine SQL-Anfrage aus, die keinen Rückgabewert hat (Create, Update und Delete Operationen). + /// + /// Typ des Objekts das die Parameter für die SQL-Query enthält. + /// Name der StoredProcedure die ausgeführt werden soll. + /// Das Objekt das die Parameter enthält. + /// Der Name des ConnectionStrings der für die Verbindung verwendet werden soll. + Task SaveData( + string storedProcedureName, + TParam parameters, + string connectionId = "Default"); +} \ No newline at end of file diff --git a/GottfriedsNackenWebseite/DataAccess/DbAccess/SqlDataAccess.cs b/GottfriedsNackenWebseite/DataAccess/DbAccess/SqlDataAccess.cs new file mode 100644 index 0000000..6193b40 --- /dev/null +++ b/GottfriedsNackenWebseite/DataAccess/DbAccess/SqlDataAccess.cs @@ -0,0 +1,38 @@ +using Dapper; +using Microsoft.Extensions.Configuration; +using System.Data; +using System.Data.SqlClient; + +namespace DataAccess.DbAccess; + +public class SqlDataAccess : ISqlDataAccess +{ + private readonly IConfiguration _config; + + public SqlDataAccess(IConfiguration config) + { + _config = config; + } + + public async Task> LoadData( + string storedProcedureName, + TParam parameters, + string connectionId = "Default") + { + using IDbConnection connection = new SqlConnection(_config.GetConnectionString(connectionId)); + + return await connection.QueryAsync(storedProcedureName, parameters, + commandType: CommandType.StoredProcedure); + } + + public async Task SaveData( + string storedProcedureName, + TParam parameters, + string connectionId = "Default") + { + using IDbConnection connection = new SqlConnection(_config.GetConnectionString(connectionId)); + + await connection.ExecuteAsync(storedProcedureName, parameters, + commandType: CommandType.StoredProcedure); + } +} \ No newline at end of file diff --git a/GottfriedsNackenWebseite/DataAccess/Models/UserModel.cs b/GottfriedsNackenWebseite/DataAccess/Models/UserModel.cs new file mode 100644 index 0000000..eed8a9e --- /dev/null +++ b/GottfriedsNackenWebseite/DataAccess/Models/UserModel.cs @@ -0,0 +1,8 @@ +namespace DataAccess.Models; + +public class UserModel +{ + public int Id { get; set; } + public string FirstName { get; set; } = string.Empty; + public string LastName { get; set; } = string.Empty; +} diff --git a/GottfriedsNackenWebseite/GottfriedsNackenDB/GottfriedsNackenDB.sqlproj b/GottfriedsNackenWebseite/GottfriedsNackenDB/GottfriedsNackenDB.sqlproj new file mode 100644 index 0000000..ab11d5c --- /dev/null +++ b/GottfriedsNackenWebseite/GottfriedsNackenDB/GottfriedsNackenDB.sqlproj @@ -0,0 +1,77 @@ + + + + Debug + AnyCPU + GottfriedsNackenDB + 2.0 + 4.1 + {79f8ac31-e467-4f7c-ac3b-cfadc3290750} + Microsoft.Data.Tools.Schema.Sql.Sql130DatabaseSchemaProvider + Database + + + GottfriedsNackenDB + GottfriedsNackenDB + 1033, CI + BySchemaAndSchemaType + True + v4.7.2 + CS + Properties + False + True + True + + + bin\Release\ + $(MSBuildProjectName).sql + False + pdbonly + true + false + true + prompt + 4 + + + bin\Debug\ + $(MSBuildProjectName).sql + false + true + full + false + true + true + prompt + 4 + + + 11.0 + + True + 11.0 + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/GottfriedsNackenWebseite/GottfriedsNackenDB/Script.PostDeployment.sql b/GottfriedsNackenWebseite/GottfriedsNackenDB/Script.PostDeployment.sql new file mode 100644 index 0000000..2b69d3e --- /dev/null +++ b/GottfriedsNackenWebseite/GottfriedsNackenDB/Script.PostDeployment.sql @@ -0,0 +1,10 @@ +/* Wird nur ausgeführt, wenn es keine Einträge in [dbo].[User] */ +IF not exists (SELECT 1 FROM [dbo].[User]) +BEGIN + INSERT INTO [dbo].[User] (FirstName, LastName) + VALUES + ('Gottfried Wilhelm', 'Leibniz'), + ('Albert', 'Einstein'), + ('Curry', 'Wurst'), + ('Brat', 'Wurst') +END diff --git a/GottfriedsNackenWebseite/GottfriedsNackenDB/dbo/StoredProcedures/spUser_Delete.sql b/GottfriedsNackenWebseite/GottfriedsNackenDB/dbo/StoredProcedures/spUser_Delete.sql new file mode 100644 index 0000000..0b7735f --- /dev/null +++ b/GottfriedsNackenWebseite/GottfriedsNackenDB/dbo/StoredProcedures/spUser_Delete.sql @@ -0,0 +1,8 @@ +CREATE PROCEDURE [dbo].[spUser_Delete] + @Id int +AS +BEGIN + DELETE + FROM [dbo].[User] + WHERE Id = @Id; +END diff --git a/GottfriedsNackenWebseite/GottfriedsNackenDB/dbo/StoredProcedures/spUser_Get.sql b/GottfriedsNackenWebseite/GottfriedsNackenDB/dbo/StoredProcedures/spUser_Get.sql new file mode 100644 index 0000000..84fdb15 --- /dev/null +++ b/GottfriedsNackenWebseite/GottfriedsNackenDB/dbo/StoredProcedures/spUser_Get.sql @@ -0,0 +1,8 @@ +CREATE PROCEDURE [dbo].[spUser_Get] + @Id int +AS +BEGIN + SELECT Id, FirstName, LastName + FROM [dbo].[User] + WHERE Id = @Id; +END diff --git a/GottfriedsNackenWebseite/GottfriedsNackenDB/dbo/StoredProcedures/spUser_GetAll.sql b/GottfriedsNackenWebseite/GottfriedsNackenDB/dbo/StoredProcedures/spUser_GetAll.sql new file mode 100644 index 0000000..fbe5376 --- /dev/null +++ b/GottfriedsNackenWebseite/GottfriedsNackenDB/dbo/StoredProcedures/spUser_GetAll.sql @@ -0,0 +1,6 @@ +CREATE PROCEDURE [dbo].[spUser_GetAll] +AS +BEGIN + SELECT Id, FirstName, LastName + FROM [dbo].[User]; +END diff --git a/GottfriedsNackenWebseite/GottfriedsNackenDB/dbo/StoredProcedures/spUser_Insert.sql b/GottfriedsNackenWebseite/GottfriedsNackenDB/dbo/StoredProcedures/spUser_Insert.sql new file mode 100644 index 0000000..acd7b61 --- /dev/null +++ b/GottfriedsNackenWebseite/GottfriedsNackenDB/dbo/StoredProcedures/spUser_Insert.sql @@ -0,0 +1,8 @@ +CREATE PROCEDURE [dbo].[spUser_Insert] + @FirstName nvarchar(50), + @LastName nvarchar(50) +AS +BEGIN + INSERT INTO [dbo].[User] (FirstName, LastName) + VALUES (@FirstName, @LastName); +END diff --git a/GottfriedsNackenWebseite/GottfriedsNackenDB/dbo/StoredProcedures/spUser_Update.sql b/GottfriedsNackenWebseite/GottfriedsNackenDB/dbo/StoredProcedures/spUser_Update.sql new file mode 100644 index 0000000..32baf35 --- /dev/null +++ b/GottfriedsNackenWebseite/GottfriedsNackenDB/dbo/StoredProcedures/spUser_Update.sql @@ -0,0 +1,10 @@ +CREATE PROCEDURE [dbo].[spUser_Update] + @Id int, + @FirstName nvarchar(50), + @LastName nvarchar(50) +AS +BEGIN + UPDATE [dbo].[User] + SET FirstName = @FirstName, LastName = @LastName + WHERE Id = @Id; +END diff --git a/GottfriedsNackenWebseite/GottfriedsNackenDB/dbo/Tables/User.sql b/GottfriedsNackenWebseite/GottfriedsNackenDB/dbo/Tables/User.sql new file mode 100644 index 0000000..3d61092 --- /dev/null +++ b/GottfriedsNackenWebseite/GottfriedsNackenDB/dbo/Tables/User.sql @@ -0,0 +1,6 @@ +CREATE TABLE [dbo].[User] +( + [Id] INT NOT NULL PRIMARY KEY IDENTITY, + [FirstName] NVARCHAR(50) NOT NULL, + [LastName] NVARCHAR(50) NOT NULL +) diff --git a/GottfriedsNackenWebseite/GottfriedsNackenWebseite.sln b/GottfriedsNackenWebseite/GottfriedsNackenWebseite.sln index 9270526..b13052d 100644 --- a/GottfriedsNackenWebseite/GottfriedsNackenWebseite.sln +++ b/GottfriedsNackenWebseite/GottfriedsNackenWebseite.sln @@ -5,7 +5,11 @@ VisualStudioVersion = 17.1.32210.238 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GottfriedsNackenWebseite", "GottfriedsNackenWebseite\GottfriedsNackenWebseite.csproj", "{464DD643-DAD9-4E16-BB24-36F789ED4C15}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GottfriedsNackenUtility", "GottfriedsNackenUtility\GottfriedsNackenUtility.csproj", "{0122762F-9961-4D28-8AA9-0D6AE7630208}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GottfriedsNackenUtility", "GottfriedsNackenUtility\GottfriedsNackenUtility.csproj", "{0122762F-9961-4D28-8AA9-0D6AE7630208}" +EndProject +Project("{00D1A9C2-B5F0-4AF3-8072-F6C62B433612}") = "GottfriedsNackenDB", "GottfriedsNackenDB\GottfriedsNackenDB.sqlproj", "{79F8AC31-E467-4F7C-AC3B-CFADC3290750}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataAccess", "DataAccess\DataAccess.csproj", "{023715EE-C9DB-417F-9B77-28BF48A30D41}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -21,6 +25,16 @@ Global {0122762F-9961-4D28-8AA9-0D6AE7630208}.Debug|Any CPU.Build.0 = Debug|Any CPU {0122762F-9961-4D28-8AA9-0D6AE7630208}.Release|Any CPU.ActiveCfg = Release|Any CPU {0122762F-9961-4D28-8AA9-0D6AE7630208}.Release|Any CPU.Build.0 = Release|Any CPU + {79F8AC31-E467-4F7C-AC3B-CFADC3290750}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {79F8AC31-E467-4F7C-AC3B-CFADC3290750}.Debug|Any CPU.Build.0 = Debug|Any CPU + {79F8AC31-E467-4F7C-AC3B-CFADC3290750}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {79F8AC31-E467-4F7C-AC3B-CFADC3290750}.Release|Any CPU.ActiveCfg = Release|Any CPU + {79F8AC31-E467-4F7C-AC3B-CFADC3290750}.Release|Any CPU.Build.0 = Release|Any CPU + {79F8AC31-E467-4F7C-AC3B-CFADC3290750}.Release|Any CPU.Deploy.0 = Release|Any CPU + {023715EE-C9DB-417F-9B77-28BF48A30D41}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {023715EE-C9DB-417F-9B77-28BF48A30D41}.Debug|Any CPU.Build.0 = Debug|Any CPU + {023715EE-C9DB-417F-9B77-28BF48A30D41}.Release|Any CPU.ActiveCfg = Release|Any CPU + {023715EE-C9DB-417F-9B77-28BF48A30D41}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/GottfriedsNackenWebseite/GottfriedsNackenWebseite/GottfriedsNackenWebseite.csproj b/GottfriedsNackenWebseite/GottfriedsNackenWebseite/GottfriedsNackenWebseite.csproj index 423398d..e38b477 100644 --- a/GottfriedsNackenWebseite/GottfriedsNackenWebseite/GottfriedsNackenWebseite.csproj +++ b/GottfriedsNackenWebseite/GottfriedsNackenWebseite/GottfriedsNackenWebseite.csproj @@ -18,6 +18,7 @@ + diff --git a/GottfriedsNackenWebseite/GottfriedsNackenWebseite/Pages/DatabaseTest.razor b/GottfriedsNackenWebseite/GottfriedsNackenWebseite/Pages/DatabaseTest.razor new file mode 100644 index 0000000..c39e988 --- /dev/null +++ b/GottfriedsNackenWebseite/GottfriedsNackenWebseite/Pages/DatabaseTest.razor @@ -0,0 +1,96 @@ +@page "/databasetest" + +@using DataAccess.Data +@using DataAccess.Models +@inject IUserData _userData + +Database Test + + + + + Nutzer + + + + + + Id + First Name + Last Name + + + + @context.Id + @context.FirstName + @context.LastName + + + + + + + + + + + + + + Neuen Nutzer erstellen: + + + Hinzufügen + + + + + +@code { + private bool _newUserValid; + + private UserModel _newUser = new(); + + private bool _loading; + + private IEnumerable _users = Enumerable.Empty(); + + protected override async Task OnInitializedAsync() + { + await RefreshUserList(); + + await base.OnInitializedAsync(); + } + + private async Task RefreshUserList() + { + _loading = true; + + try + { + _users = await _userData.GetUsers(); + } + catch (Exception e) + { + Console.WriteLine($"Failed to load users. Exception: {e}"); + } + + _loading = false; + } + + private async Task AddUser() + { + await _userData.InsertUser(_newUser); + + await RefreshUserList(); + + _newUser = new UserModel(); + } + + private async Task DeleteUser(UserModel user) + { + await _userData.DeleteUser(user.Id); + + await RefreshUserList(); + } +} diff --git a/GottfriedsNackenWebseite/GottfriedsNackenWebseite/Program.cs b/GottfriedsNackenWebseite/GottfriedsNackenWebseite/Program.cs index a2e20cb..4772f7a 100644 --- a/GottfriedsNackenWebseite/GottfriedsNackenWebseite/Program.cs +++ b/GottfriedsNackenWebseite/GottfriedsNackenWebseite/Program.cs @@ -1,3 +1,5 @@ +using DataAccess.Data; +using DataAccess.DbAccess; using GottfriedsNackenWebseite.Data; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Web; @@ -11,6 +13,9 @@ builder.Services.AddServerSideBlazor(); builder.Services.AddSingleton(); builder.Services.AddMudServices(); +builder.Services.AddSingleton(); +builder.Services.AddSingleton(); + var app = builder.Build(); // Configure the HTTP request pipeline. diff --git a/GottfriedsNackenWebseite/GottfriedsNackenWebseite/Shared/NavMenu.razor b/GottfriedsNackenWebseite/GottfriedsNackenWebseite/Shared/NavMenu.razor index c7e004f..42233c3 100644 --- a/GottfriedsNackenWebseite/GottfriedsNackenWebseite/Shared/NavMenu.razor +++ b/GottfriedsNackenWebseite/GottfriedsNackenWebseite/Shared/NavMenu.razor @@ -23,6 +23,9 @@ Nacken Numberle + + Datenbank Test + @*