Czy w repozytorium mogą znaleźć się zapytania sql?

0

Czy dopuszczalne z punktu widzenia dobrych praktyk jest umieszczanie w Repository zapytan sql?
Uzywam Dappera. Może dam przykłąd jak to mniej wiecej robie:

interface IInvoiceRepository
{
   //jakiś kod
   IEnumerable<Invoice> GetAll();
}

public class InvoiceSqlRepository : IInvoiceRepository
{
   //jakiś kod

   public IEnumerable<Invoice> GetAll()
   {
      string sql = "SELECT * FROM Invoice;";

     using (var connection = My.ConnectionFactory())
     {
       connection.Open();
       var invoices = connection.Query<Invoice>(sql).ToList();
       return invoices;
     }
   }
}
0

Jeśli już musisz pisać takie gołe SQL'e to odpowiedź brzmi: tak (niby gdzie indziej miałbyś je trzymać?). Ale znaczna większość programistów preferowałoby użycie ORM'a. Zainteresuj się Entity Framework.

PS: Mogłoby to wyglądać jakoś tak:

var blog = context.Invoices
                    .Where(invoice => invoice.Name == "ADO.NET Blog") 
                    .FirstOrDefault(); 
2

Bez przesady z tym Entity Frameworkiem. Gdy potrzebna jest wydajność to się tego nie używa. Przy złożonych zapytaniach Entity generuje bardzo niewydajny SQL i lepiej go napisać samemu. Entity nadaje się najlepiej do prostych selectów i upsertów. W większych systemach nie na prawa bytu. Chyba, że ktoś lubi jak zapytanie wykonuje się 800ms zamiast 30 :) Ale przyznam, że Entity jest ok, gdy odpalamy procedury, wtedy potrafi to sobie fajnie zmapować.

Do autora: zapytania SQL można trzymać w repozytorium. Jeżeli są bardziej złożone to może lepszym pomysłem by było trzymanie ich w osobnych plikach .sql jako Embedded Resource lub napisanie klasy, która zarządza twoimi zapytaniami.

0

@TomRiddle: chce użyć ORMa w postaci Dappera a on czasem wymaga zeby pisac kod sql.

1

Przejście z Dappera na EF to raczej krok wstecz.
W takim przypadku kod SQL jest w porządku, gdyby chcieć go wydzielić z repozytorium, to trzeba by stworzyć jakiś wrapper na Dappera, który nie robiłby za bardzo nic poza byciem wrapperem, co jest lekko bez sensu.
No i tak tradycyjnie, to mogę się założyć, że ani tak naprawdę nie masz repozytoriów, ani ich nie potrzebujesz.

0

@somekind: nazywanie tego repozytorium to rzeczywiscie troche na wyrost. Po prostu chce klase ktora bedzie siegała do bazy i dostarczała/zapisywa dane dla modelu. Czy taka klasa mogła by wygladać tak jak to "repozytorium" ktore przedstawiłem?

0

No ja tam nie widzę niczego, czego sam bym nie napisał. Tylko ja bym to nazwał InvoiceProvider albo jakoś tak. ;)

0

Dzięki @somekind. A czy poprawne było by tez jakbym w warstwie Core miał wlasnie ten interface:

interface IInvoiceProvider
{
   //jakiś kod
   IEnumerable<Invoice> GetAll();
}

a w infrastrukturze implementację

public class InvoiceSqlProvider : IInvoiceProvider
{
   //jakiś kod

   public IEnumerable<Invoice> GetAll()
   {
      string sql = "SELECT * FROM Invoice;";

     using (var connection = My.ConnectionFactory())
     {
       connection.Open();
       var invoices = connection.Query<Invoice>(sql).ToList();
       return invoices;
     }
   }
}

W takim kierunku można podążać, czy ten interface w Core jest zbędny?

0

Jeśli będziesz miał interfejs, to będziesz mógł go zamockować w testach jednostkowych klas, które go używają. To jedyny zysk z jego istnienia.

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