Come dovrei organizzare le comuni query di linq (o anche query SQL)?

0

Uso Entity Framework. Diciamo che ho una query linq davvero complessa, che mi serve in più parti della mia applicazione, alcuni servizi, alcuni controller.

C'è qualche schema di progettazione che dovrei seguire?

Per prima cosa ho pensato che il Pattern del Repository sarebbe stato perfettamente valido:

MyDto myRepository.GetDataFromComplexQuery();

Ma non dovremmo usare Schema del repository con Entity Framework . La risposta nella domanda collegata sta invece parlando dell'utilizzo dei Servizi. Tuttavia, non voglio far bollire le mie classi di servizio con molte (duplicate) logiche di query complesse.

Quindi mi chiedo come dovrei progettarlo e come organizzarlo nella soluzione?

Qualcosa di simile a questo sembra molto sbagliato:

namespace Foo.Data.DataHelpers
{
    public class ComplexQuery
    {
        private DbContext _ctx;

        public ComplexQuery(DbContext ctx)
        {
            _ctx = ctx;
        }

        public MyDto GetData()
        {
            query = //...
            return query.Single();
        }
    }
}

Anche a volte la query è complessa e deve essere sostituita dal semplice vecchio SQL per motivi di prestazioni. Ma non penso, questo cambierebbe la risposta?

    
posta Christian Gollhardt 23.07.2017 - 23:30
fonte

1 risposta

1

Penso che per "schema di servizio" la risposta raccomandi di utilizzare un'interfaccia che astrae la fonte del dati. Si differenzia dal modello di repository in quanto il pattern del repository è un'astrazione che modella un'origine dati come se fosse una raccolta con operazioni per elencare, aggiornare e creare nuovi elementi. Mentre i servizi astraggono le azioni richieste dal cliente in un approccio di richiesta-risposta. La denominazione del servizio dipenderà dallo scopo delle query e si raggrupperanno query simili sotto lo stesso servizio. Nell'esempio seguente, utilizzo il dominio della creazione di report come dominio che richiede alcune query complesse.

interface IReportDataService {
  MyDto getReportData();
} 

public class DbReportDataService : IReportDataService {
  private DbContext _ctx;

  public DbReportDataService(DbContext ctx) {
    _ctx = ctx;
  }

  MyDto IReportDataService.getReportData() {
    query = //...
    return query.Single();
  }
}

// Usage
public class ReportBuilder {
  private IReportDataService _dataService;

  public ReportBuilder(IReportDataService dataService) {
    _dataService = dataService;
  }

  public Report fillReport(...) {
    MyDto data = _dataService.getReportData();
  }
}

Usando questa astrazione, puoi testare l'unità ReportBuilder con il mocking %codice%. L'implementazione può utilizzare gli script Linq o SQL: non importa a IReportDataService . La composizione root dovrebbe costruire una singola istanza di ReportBuilder e iniettarla nei componenti che ne hanno bisogno ( DbReportDataService ).

    
risposta data 24.07.2017 - 00:03
fonte

Leggi altre domande sui tag