NET 6 WebAPI - aplikacja wspierające więcej niż jedną technologie bazodanową

0

Witam.
Pierwsze, najważniejsze pytanie - czy to w ogóle jest warte zachodu? Zastanawiam się, czy nie dołożyć wsparcia więcej niż jednej technologii bazodanowej. Chciałbym użyć trzech z popularnych - MySQL, SQL Server oraz Postgres. ORM to Dapper.

  1. Jak ogarnąć ConnectionStringi?
  2. Skąd mam wiedzieć, którego użyć - SqlConnection, MySqlConnection, NpgsqlConnection - serwis do SQL będzie jednym wielkim "bałaganem".
  3. Co w kwestii parametrów? Wiem, że różne connectory różnie interpretują dapperowskie parametry. W SqlConnection jest @Id, w OleDbConnection jest ?id?.

Mam wrażenie, że za dużo sobie na głowę wrzucam. Może teraz do aplikacji webowych lepiej użyć jakiegoś NoSQL, tylko wtedy tracę relacje, a może być ich kilka.

PS.
Wziąłem taki problem pod uwagę, bo chciałbym dać możliwość wyboru klientowi, który wdrażałby oprogramowanie u siebie na serwerze. Nie każdy sobie radzi z instalacją SQL Server poprawnie.

1
  1. Oczywiście że w zewnętrznym zastosowaniu użyć Connection o po którym dziedziczą konkretne. Te mają prawo ujawnić się najwyżej w fabryce czy czymś podobnym, która pozyskuje połączenie
3

Wziąłem taki problem pod uwagę, bo chciałbym dać możliwość wyboru klientowi, który wdrażałby oprogramowanie u siebie na serwerze.

A to nie wystarczy abyś miał jakiś interfejs IBazka, implementacje dla 3 bazek i na podstawie np. appsettings.json rejestrował w DI że dla IBazka ma iść np. PostgresBazka z danym conn. str?

2

Zakładam, że jeden klient -> jedna instancja aplikacji -> jedna instancja bazy danych (SQL Server lub MySQL lub Postgres).

Punkty 1 i 2 są proste, można zaimplementować jak nizej:

  1. Connection string najprościej przechowywać w appsettings.json
  2. Ustawienie typu bazy danych w appsettings.json i fabryka do wyboru odpowiedniego typu Connection. Jeśli dobrze pamiętam to wszystkie wymienione typy Connection dziedziczą po klasie DbConnection. Więc na podstawie configu fabryka jest w stanie utworzyć instancję odpowiedniego typu, coś w stylu:
{
  "databaseConfig": {
    "provider": "SqlServer",
    "connectionString": "..."
  }
}
public class MyConnectionFactory
{
  private readonly DatabaseConfig _databaseConfig;
  
  public MyConnectionFactory(IOptions<DatabaseConfig> databaseConfig)
  {
    _databaseConfig = databaseConfig.Value;
  }
  
  public DbConnection Create()
  {
    if (_databaseConfig.Provider == DatabaseProvider.SqlServer)
      return new SqlConnection(_databaseConfig.ConnectionString);

    if (_databaseConfig.Provider == DatabaseProvider.Postgres)
      return new NpgsqlConnection(_databaseConfig.ConnectionString);

    // itd...
  }
}

Odnośnie punktu 3 to jest to skomplikowane ze względu na różnice w składni pomiędzy silnikami baz danych. O ile w prostych zapytaniach nie będzie wielkiej różnicy, o tyle w tych bardziej złożonych trzeba by uwzględnić coś na zasadzie query buildera, który w zależności od wybranego providera będzie budował zapytanie sql zoptymalizowane pod konkretny silnik bazodanowy.

Takie coś zostało już zaimplementowane w Entity Framework, więc jeżeli chcesz wspierać różne silniki bez konieczności pisania ręcznej obsługi tego wszystkiego to rozważ migrację do EF.

1

Pytanie dlaczego chcesz to robić. Jak tak na wszelki wypadek to nie warto. Jak już to mssqla i postgresa. A co do nosql to zależy jakie dane ile ich będzie i co chcesz z nimi robić.

0

@markone_dev: Odkąd wyszło .NET Core to EF się troszkę "zepsuł". Nie wszystkie funkcje zostały przeniesione z .NET Framework. Głównie chodzi mi o czysty SQL, gdzie EF Core ma FromSqlRaw(), ale działa tylko na encji, a ja, na przykład, do raportów potrzebuje na całym kontekście wykonać swoje zapytanie.

@S4t: To nie jest ogromny projekt, nie będzie dużo danych, będzie za to kilka relacji. Raportowanie robię swoje. Jeśli będą jakiekolwiek analizy to raczej w formie takiego raportu gdzie tylko filtruje dane i wyświetlam w tabelce. Wychodzi na to, że chce to zrobić tak na wszelki wypadek.

0

Generalnie po to masz orm żeby nie musieć pisać czystego sqla, dlatego dobrze użyty EF pozwala zmienić bazę danych wyłącznie przy pomocy konfiguracji. Jak dodajesz czysty sql to z automatu tracisz tą uniwersalność. Wiadomo że nie ma róży bez kolców i ormy mają swoje ograniczenia, dlatego trzeba to dobrze przemyśleć idąc na kompromis tracąc elastyczność sqla ale zyskując uniwersalność w dostępie do silników baz danych.

Jezeli nie masz dużej ilości danych i nie potrzebujesz super wydajności, to rozważ bazę która nie wymaga instalacji taką jak Sqlite.

0

@AdamWox: przecież w DbContext masz właściwość Database i tam możesz użyć różnych metod do wykonania SQL np.: tutaj dokumentacja

0
int ExecuteSqlRaw

To zadziała tylko gdybym chciał zrobić INSERT, UPDATE lub DELETE. Nie wyciągnę tym danych (SELECT) zwracając swój typ.

1
AdamWox napisał(a):

Mam wrażenie, że za dużo sobie na głowę wrzucam. Może teraz do aplikacji webowych lepiej użyć jakiegoś NoSQL, tylko wtedy tracę relacje, a może być ich kilka.

Zależy od "umiejscowienia" aplikacji. Księgowo-sprzedazowe-magazynowe-kadowe JEDYNIE w relacyjnych. Bazy wiedzy (wszelakiej) być może w NoSQL, choć w 95% przypadków da się ładnie zaprojektować w relacyjnych.
Analityczne-historyczne "po fakcie" (czy słówko OLAP już jest niemodne) to jeszcze inne akcenty

0
ZrobieDobrze napisał(a):

Zależy od "umiejscowienia" aplikacji. Księgowo-sprzedazowe-magazynowe-kadowe JEDYNIE w relacyjnych.

Trochę dogmatyczne podejście. Spójność referencyjna jest pomocna, ale nie jest konieczna do tego, żeby dane były spójne, poza tym źle zaprojektowana relacyjna baza też może być niespójna(w sensie biznesowym).

2

@Saalin:

Nie tylko o projekt, ale i efektywne w praktyce wyszukiwania po "liściach" informacji itd...
Świadomie zaprojektowane indeksy vs "indeksowanie wszystkiego co się rusza / niczego dobrze" w dokumentowych.

Święta wojna sztywnego projektu relacyjnych / elastyczności b.d. dokumentowych

Kiedyś do projektu finansowo-podobnego przyszedł człowiek o rodowodzie biznesu webowego. Proponował przeszukiwanie danych analitycznych "po tagach". Musiało to być dość rozrywkowe, skoro do dziś zapamiętaliśmy

No jednak (tak sobie przedstawiam) całą uniwersytecka teoretyczna podbudowa r.b.d. powstała na praktyce już istniejących rozwiązań do liczenia pieniążków (mainframy, te sprawy). To jest kilkadziesiąt lat razem, i sprawdzone do bólu.

0
AdamWox napisał(a):

@markone_dev: Odkąd wyszło .NET Core to EF się troszkę "zepsuł". Nie wszystkie funkcje zostały przeniesione z .NET Framework. Głównie chodzi mi o czysty SQL, gdzie EF Core ma FromSqlRaw(), ale działa tylko na encji, a ja, na przykład, do raportów potrzebuje na całym kontekście wykonać swoje zapytanie.

No to tam, gdzie się da użyć ORMa, a do raportów użyć customowej implementacji.
A poza tym, to raporty chyba lepiej mieć po stronie bazy.

0

@somekind: co znaczy raporty chyba lepiej mieć po stronie bazy? U mnie raport to tylko odpowiednio pofiltrowane dane - producent, zakresy dat, typ akcji, typ urządzenia.

U mnie raporty nie są w żaden sposób predefiniowane.

3

No to jeśli danych jest mało, to ORM sobie poradzi. Jeśli dużo, to lepszy będzie widok bazodanowy.

1 użytkowników online, w tym zalogowanych: 0, gości: 1