3 messaggi dal 30 aprile 2022
Salve a tutti ,
Ho una domandata più teorica che pratica , se ho una classe che definisce una area di un problema come potrebbe essere la gestione e l'aggiunta di una macchina in un comparto auto , in questa classe ci saranno dei metodi che gestiscono l'auto, come ad esempio dammi tutte le auto , oppure dammi solo un auto o tutte le auto blu, questi metodi che conterranno quindi delle QueryLINQ per soddisfare le varie richieste ….ora mettiamo caso che io dovessi fare una classe come un amministratore che gestisce la modifica e la creazione e l'aggiunta delle auto , ho pensato di creare un’altra classe che conterrà i metodi contenenti le QueryLINQ , ma la mia domanda è questa , quando faccio le QueryLINQ per cambiare /eliminare un auto oppure per spostare l’auto da un parco ad un altro etc etc , le auto le prenderei le direttamente dalla QueryLINQ del metodo della classe amministratore , ma è sbagliata come cosa?
Non dovrei creare un metodo dentro la classe che gestisce le auto, il quale viene richiamato dalla classe amministratore?


Ad esempio Eliminazione : 

  Public Class Auto{

     public Task<Car> MacchineRosse(int idcar)
    {
      return  Cars cars = db.Car.Where(x=>x.idcar=idcar && x.Colore="Rosso").ToList();
     }
    
}
  
Public Class Amministratore {
   
 public Task  EliminaMacchineRosse(int idcar)
 {
   cars = Auto.MacchineRosse(idcar);
  db.Remove(car)
  db.SaveChangesAsync();
    
  }

}
  
  
  ---------------OPPURE----------------
  
  
Public Class Amministratore {

   public Task<bool> EliminaMacchineRosse(int idcar)
  {
     Car car  = db.Car.Where(x=>x.idcar=idcar && x.colore= "Rosso").ToList();
     db.Remove(car)
   db.SaveChangesAsync();
    
  }
  }
  



Mi è sorto questo dubbio perché in un progetto leggermente più complesso , potrei avere bisogno di leggere solo una parte di un auto , oppure creare dei modelli appositi che contengono più valori da altri classi , questo vorrebbe dire fare ogni 3 x 2 un metodo che mi renda quello che cerco nella classe ,per poi utilizzarlo nella classe in questione , quindi intasando le classi di metodi che possono essere superflui e creando una sorta di Ping Pong.

Grazie per chi risponderà
Ciao!
non sono sicuro di aver capito al 100% la domanda ma da quanto ho capito io in genere gestisco il problema in questo modo:
Per ogni entità rappresentata in un database (una tabella) , ho una classe repository che contiene tutti i metodi che l'applicazione richiede..
In genere serve un interfaccia e la sua implementazione, qualcosa del genere:

 public interface  ICarsRepository
    {
        IEnumerable<Car> GetAll();
        IEnumerable<Car> DeleteCarByColor(string color);
    }

 public class CarsRepository : ICarsRepository
    {
        private readonly IDatabaseService db;
        public CarsRepository(IDatabaseService _db)
        {
            db = _db;
        }

        public async IEnumerable<Car> GetAll()
        {
            return await db.Car.ToList();
        }

        public async IEnumerable<Car> DeleteCarByColor(string color)
        {
            var cars = await db.Car.Where(x => x.colore = color).ToList();
            foreach (var car in cars)
            {
                db.Remove(car);
            }
           
            db.SaveChangesAsync();
        }

    }


In questo modo tutte le altre classi/servizi (amministratore o altro) richiameranno questa repository per la gestgione delle chiamate e ognuna di queste classi potrà avere dei metodi personalizzati.

 public class AmministratoreService
    {
        private readonly ICarsRepository _carsRepository;

        public AmministratoreService(ICarsRepository carsRepository)
        {
            this._carsRepository = carsRepository;
        }

        public async Task DeleteRedCars()
        {
          await  _carsRepository.DeleteCarByColor("red");
        }
    }


In sostanza in applicazione non troppo complesse una singola classe repository esporrebbe una serie di metodi per il richiamo e modifica di dati e le altre classi come amministratore hanno dei metodi specifici in base alla necessità che comunque utilizzano la classe repository per la loro risoluzione (vedi DeleteRedCars in amministratore che richiama il metodo DeleteCarByColor con un parametro nella classe repository)
In applicazione più complesse potrebbero esserci più repository riferite alla singola entità ad esempio:
- un autoReaderRepository per tutte le query che dovranno solo ad andare a leggere dei dati
- un autoChangeRepository per tutte le query che effettuano modifiche.
E nelle vari classi/servizi fare riferimento alla repository che serve.

Questi sono ovviamente solo degli esempio, non sono per forza quelli più "giusti" o migliori.
Spero di essere chiaro e soprattutto di essere stato utile
A disposizione
grazie

Maurizio
3 messaggi dal 30 aprile 2022
ok se non ho capito male , non avendo una tabella Amministratore i metodi di amministratore utilizzano soltanto i metodi delle entità rappresentata dal database e non utilizzano a loro volta il database , del tipo se l'amministratore vorrebbe cambiare oltre al colore anche il modello delle gomme di taglia 18, dovrebbe essere creato un nuovo metodo sull'interfaccia ICarsRepository che poi viene implementato sulla classe CarsRepository , dove farà il mestiere richiesto.

però cosi mi perderebbe il senso di utilizzare la classe amministratore , perché se richiama solamente delle funzioni sottostanti , potrebbe farlo direttamente il controller quando gli arriva una richiesta HTTP, chiamando le funzioni inerenti.

Quindi la mia logica è comunque sbagliata utilizzando una classe che non ha una reale rappresentanza su database per comporre delle Query, perché possono essere sempre e frutto di Metodi delle classi che hanno una reale rappresentanza su db.
Modificato da Cento il 20 agosto 2022 15:03 -
Non è sbagliato usare classi che non hanno una rappresentanza logica del database , anzi spesso a mio avviso è consigliato se la logica di ciò che rappresenta il tuo programma lo richiede.
Metti che l'amministratore oltre a cambiare dettagli delle auto ha la responsabilità di gestire anche del personale:
All'interno dell'amministratoreService avrai sia i metodi per la gestione delle macchine (che useranno la carsRepository) che i metodi per la gestione del personale (che useranno la userRepository ad esempio)

  public class AmministratoreService
    {
        private readonly ICarsRepository _carsRepository;
        private readonly IJobsRepository _jobsRepository;

        public AmministratoreService(ICarsRepository carsRepository, IJobsRepository jobs)
        {
            this._carsRepository = carsRepository;
            this._jobsRepository = jobs;
        }

        public async Task DeleteRedCars()
        {
          await  _carsRepository.DeleteCarByColor("red");
        }

        public async Task ModificaModelloGomme(Car car)
        {
            car.ModelloGomma = "modello2";
            await _carsRepository.Update(car);
        }

        public async Task ModificaColoreCarrozzeria(Car car)
        {
            car.ColoreCarrozzeria = "red";
            await _carsRepository.Update(car);
        }

        public async Task AssegnaJob(User user)
        {
            user.Job = new Job();
            await _jobsRepository.AddJob(user.Job, user.id);
        }
    }


Nel database tu avrai in questo esempio la tabella cars e la tabella jobs ma non la tabella amministratore.. ma in questo modo nell'applicazione (e nel codice sorgente) la responsabilità dell'amministratore e le funzioni che esegue sono rappresentate dalla classe amministratoreService.

Ripeto, è solo uno dei tanti modi per gestire la cosa, non è LA soluzione
Maurizio
3 messaggi dal 30 aprile 2022
Vedo nei tuoi ottimi esempi che hai postato la classe amministratore non ha direttamente utilizzato delle query tipo
var cars = await db.Car.Where(x => x.colore = color).ToList();
ma demanda al servizio apposito , e mi fa pensare che il metodo che ho usato io schiaffandoci direttamente le Query per arrivare alla logica che mi serviva .....non sia un metodo giusto o la soluzione giusta.


Ti ringrazio Maurizio per gli ottimi consigli che mi stai dando e il supporto.
Figurati grazie a te.
Io in genere richiamo una classe repository dedicata invece che direttamente la query per 2 motivi:
- se hai necessità di modificare correggere una query per qualunque motivo dovrai poi farlo su tutte le classi in cui la usi.. mentre se la query vera e proprio è all'interno del repository potrai modificarla solo li dentro e automaticamente tutti i servizi che usano quella repository saranno aggiornati e corretti.
- se un giorno deciderai di passare da usare entity framework a dapper o qualunque altra cosa dovrai modificare di nuovo tutte le classi. Invece richiamando una repository (ancora meglio la sua interfaccia) potrai semplicemente creare la nuova implementazione con la stessa interfaccia e di nuovo non dovrai modificare tutte le classi dove usavi la query.

Se qualcosa non ti è chiaro o hai qualche domanda (a cui so rispondere) chiedi pure.
A disposizione.
Maurizio

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.