Databasanslutningar till olika databaser i ASP.Net Core

Permalänk

Databasanslutningar till olika databaser i ASP.Net Core

Jag håller på att utveckla ett nytt API i ASP.Net Core som ska ersätta ett befintligt PHP-baserat API.

Alla kunder har en egen databas (MySql) och jag använder Basic Authentication för att identifiera användaren/kunden och hämtar dennes databasuppgifter från en central databas.

I Startup.cs har jag lagt till min databasklass som en Singleton

services.AddSingleton<IDbConnection, MySqlConnection>();

och det är denna instans av MySqlConnection-klassen jag använder för att hämta kundens inloggningsuppgifter från den centrala databasen och för att ansluta och hämta data från kundens databas.

Så här ser MySqlConnection-klassen ut (jag har tagit bort övriga CRUD-funktioner förutom Get):

using System; using System.Collections.Generic; using System.Linq; using System.Net.Http.Headers; using System.Text; using API.Db.Interfaces; using API.Helpers; using Dapper; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; namespace API.Db { public class MySqlConnection : ControllerBase, IDbConnection { private readonly IHttpContextAccessor _context; public MySqlConnection(IHttpContextAccessor context) { _context = context; if (context.HttpContext == null) throw new Exception("No content..."); SimpleCRUD.SetDialect(SimpleCRUD.Dialect.MySQL); } public T Get<T>(int id) { using System.Data.IDbConnection connection = new MySql.Data.MySqlClient.MySqlConnection(ConnectionString()); return connection.Get<T>(id); } private string ConnectionString() { var apiUser = GetApiUser(_context.HttpContext?.Request.Headers); return $"Server={apiUser.DbHost};Database={apiUser.DbDatabase};Uid={apiUser.DbUser};Pwd={apiUser.DbPwd};Port={apiUser.DbPort}"; } private static ApiUserModel GetApiUser(IHeaderDictionary headers) { var authHeader = AuthenticationHeaderValue.Parse(headers["Authorization"]); var credentialsByes = Convert.FromBase64String(authHeader.Parameter ?? string.Empty); var credentials = Encoding.UTF8.GetString(credentialsByes).Split(':'); var username = credentials[0]; var password = credentials[1]; using System.Data.IDbConnection connection = new MySql.Data.MySqlClient.MySqlConnection("Server=db.exempel.se;Port=3306;Database=ApiAccounts;Uid=användarnamn;Pwd=lösenord;"); var user = connection.Query<ApiUserModel>("SELECT * FROM users WHERE username = @Username AND password = @Password;", new { Username = username, Password = password }).SingleOrDefault(); return user; } } }

Är detta ett korrekt sätt att implementera anslutningar för olika databaser eller var har jag tänkt fel?

Permalänk
Medlem

Det känns lite konstigt att din DbConnection är en controller. Jag skulle nog bryta ut allt databas-relaterat till en egen klass med interface, registrera som en service och ta in i konstruktorn i controllern. Sen kan det va lite lurigt att hantera db connections själv, brukar kunna va bättre att använda en connection pool men jag har inte använt mysql i asp net så det kanske är så man ska göra.

Permalänk
Medlem

Använd EF core och skapa upp en dbcontext per databas. Varför måste du hämta inloggningsuppgifter via httpanrop, ändras de frekvent? Kan du inte lägga alla connectionstrings i appsettings?

Sen håller jag med ovanstående, en controller ska inte användas som en databasconnection. En controller ska bara definera routes, skickar requests vidare och skicka tillbaka ett svar.

Sedan finns redan HttpContext per automatik i controllers via basklassen, så du behöver inte använda HttpContextAccessor i controllers. HttpContextAccessor används för att komma åt requestdata utanför controllern vid behov, helst ska du hämta allt du behöver i controllen och skicka det vidare med din dto.

Permalänk
Skrivet av DarkBob:

Det känns lite konstigt att din DbConnection är en controller. Jag skulle nog bryta ut allt databas-relaterat till en egen klass med interface, registrera som en service och ta in i konstruktorn i controllern. Sen kan det va lite lurigt att hantera db connections själv, brukar kunna va bättre att använda en connection pool men jag har inte använt mysql i asp net så det kanske är så man ska göra.

Tack för notisen om Controller-arvet i MySqlConnection som nu är borttagen.

Gällande Connecition Pooling, så används det automatiskt av MySql.Data.MySqlClient.MySqlConnection().

Skrivet av zaibuf:

Använd EF core och skapa upp en dbcontext per databas. Varför måste du hämta inloggningsuppgifter via httpanrop, ändras de frekvent? Kan du inte lägga alla connectionstrings i appsettings?

Sen håller jag med ovanstående, en controller ska inte användas som en databasconnection. En controller ska bara definera routes, skickar requests vidare och skicka tillbaka ett svar.

Sedan finns redan HttpContext per automatik i controllers via basklassen, så du behöver inte använda HttpContextAccessor i controllers. HttpContextAccessor används för att komma åt requestdata utanför controllern vid behov, helst ska du hämta allt du behöver i controllen och skicka det vidare med din dto.

Jag vill helst inte använda EF Core då jag tycker det abstraherar bort alldeles för mycket och det kommer bita mig i rumpan en vacker dag när något inte fungerar Jag föredrar Dapper.

Gällande den centrala databasen, så hämtar jag inte enbart inloggningsuppgifter utan även en massa andra inställningar och rättigheter. Jag använder även databasen för att logga olika prylar. Dessutom hämtar/skriver andra system till/från den databasen, så det kan ske ändringar när som helst.

Jag har tagit bort Controller-arvet i MySqlConnection, men då är det väl rätt att använda HttpContextAccessor i MySqlConnection?

Permalänk
Medlem
Skrivet av Gutenisse:

Jag vill helst inte använda EF Core då jag tycker det abstraherar bort alldeles för mycket och det kommer bita mig i rumpan en vacker dag när något inte fungerar Jag föredrar Dapper.

Du får ju manuellt uppdatera queries i din kod om det blir schema ändringar tillskillnad från att bara läsa om modellerna från databasen, men gör det du föredrar. Tänkte bara spara dig tid då du inte kontrollerar databasen men behöver ändå gå mot den.

Citat:

Dessutom hämtar/skriver andra system till/från den databasen, så det kan ske ändringar när som helst.

Det där låter ju inte något vidare. Varför delar du databas med flera andra system så att en ändring kan slå ut flera andra apier? Spaghetti deluxe.

Citat:

Jag har tagit bort Controller-arvet i MySqlConnection, men då är det väl rätt att använda HttpContextAccessor i MySqlConnection?

Jag kan tycka att ditt datalager inte ska gå direkt mot HttpRequesten från HttpContext. Din Controller bör hämta ut all data som behövs och skicka det vidare till din service/repository inbakat i en dto.

Permalänk
Skrivet av zaibuf:

Du får ju manuellt uppdatera queries i din kod om det blir schema ändringar tillskillnad från att bara läsa om modellerna från databasen, men gör det du föredrar. Tänkte bara spara dig tid då du inte kontrollerar databasen men behöver ändå gå mot den.

Det där låter ju inte något vidare. Varför delar du databas med flera andra system så att en ändring kan slå ut flera andra apier? Spaghetti deluxe.

Jag kan tycka att ditt datalager inte ska gå direkt mot HttpRequesten från HttpContext. Din Controller bör hämta ut all data som behövs och skicka det vidare till din service/repository inbakat i en dto.

De enda tabelländringarna som görs är att det kan tillkomma nya kolumner och det är jag som lägger till sådana. Befintliga kolumner ändrar aldrig namn eller tas bort, så en simpel "SELECT * FROM tabel" fungerar alltid
Och det är enbart våra egna system som har åtkomst till den centrala databasen. Externa parter hämtar och skriver data till kundernas databaser via API't.

Ska ändra så HttpRequesten skickas från Controllerna istället. Inte för att jag riktigt förstår fördelen med det, men jag utgår från att du har rätt och förhoppningsvis ramlar polletten ner när jag gör ändringarna

Och tack för dina svar, förresten!